home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacGambit 2.0 / sources2 / Interp⁄Comp (.scm) / target-m68000-1.scm < prev    next >
Encoding:
Text File  |  1992-09-08  |  134.4 KB  |  3,302 lines  |  [TEXT/gamI]

  1. ;==============================================================================
  2.  
  3. ; file: "target-m68000-1.scm"
  4.  
  5. ;------------------------------------------------------------------------------
  6. ;
  7. ; Target machine abstraction (for M68000):
  8.  
  9. ; The virtual machine implementation is a mapping of PVM instructions
  10. ; and operands to M68000 instructions and operands.  The mapping of
  11. ; operands is fairly simple because M68000 operands form a superset of
  12. ; PVM operands.  PVM registers are mapped to M68000 registers, the PVM stack
  13. ; is implemented with the M68000's stack and global variables are
  14. ; implemented by an array of objects.
  15. ;
  16. ; The M68000's registers are dedicated as follows:
  17. ;
  18. ; D0      temporary register (also used as the argument count register)
  19. ; D1..D4  PVM registers 1 to 4
  20. ; D5      interrupt countdown timer (low 16 bits)
  21. ; D6      always = () = 11101111111011111110111111101111 (placeholder mask)
  22. ; D7      always = #f = 11110111111101111111011111110111 (pair mask)
  23. ;
  24. ; A0      PVM register 0 (mostly used to hold the return address)
  25. ; A1..A2  temporary registers (to implement PVM instructions)
  26. ; A3      heap allocation pointer (grows downwards)
  27. ; A4      lazy task queue tail pointer (grows downwards)
  28. ; A5      always = pointer to the processor's state (local variables)
  29. ; A6      always = pointer to the global variable table and code area
  30. ; A7      stack pointer (grows downwards)
  31.  
  32. ;------------------------------------------------------------------------------
  33.  
  34. (define (begin! info-port targ) ; initialize package
  35.  
  36.   (set! return-reg (make-reg 0))
  37.  
  38.   (target-end!-set!         targ end!)
  39.   (target-dump-set!         targ dump)
  40.   (target-nb-regs-set!      targ nb-pvm-regs)
  41.   (target-prim-info-set!    targ prim-info)
  42.   (target-label-info-set!   targ label-info)
  43.   (target-jump-info-set!    targ jump-info)
  44.   (target-proc-result-set!  targ (make-reg 1))
  45.   (target-task-return-set!  targ return-reg)
  46.  
  47.   (set! *info-port* info-port)
  48.  
  49.   '())
  50.  
  51. (define (end!) ; finalize package
  52.   '())
  53.  
  54. (define *info-port* '())
  55.  
  56. ;------------------------------------------------------------------------------
  57. ;
  58. ; Usage of registers:
  59.  
  60. (define nb-pvm-regs 5) ; Number of registers in the virtual machine.
  61.  
  62. (define nb-arg-regs 3) ; Number of registers used to pass arguments.
  63.  
  64. ;------------------------------------------------------------------------------
  65. ;
  66. ; Size of an object pointer
  67.  
  68. (define pointer-size 4)
  69.  
  70. ;------------------------------------------------------------------------------
  71. ;
  72. ; Primitive procedure database:
  73.  
  74. (define prim-proc-table
  75.   (map (lambda (x)
  76.          (cons (string->canonical-symbol (car x))
  77.                (apply make-proc-obj (car x) #t #f (cdr x))))
  78.        prim-procs))
  79.  
  80. (define (prim-info name)
  81.   (let ((x (assq name prim-proc-table)))
  82.     (if x (cdr x) #f)))
  83.  
  84. (define (get-prim-info name)
  85.   (let ((proc (prim-info (string->canonical-symbol name))))
  86.     (if proc
  87.       proc
  88.       (compiler-internal-error
  89.         "get-prim-info, unknown primitive:" name))))
  90.  
  91. ;------------------------------------------------------------------------------
  92. ;
  93. ; Procedure calling convention:
  94.  
  95. (define (label-info min-args nb-parms rest? closed?)
  96.  
  97. ;  * return address is in reg(0)
  98. ;
  99. ;  * if nb-parms <= nb-arg-regs,
  100. ;
  101. ;      then, parameter `n' is in reg(n)
  102. ;
  103. ;      else, the first `m' = nb-parms - nb-arg-regs
  104. ;            parameters will be on the stack and parameter `n' is in
  105. ;
  106. ;            reg(n - m), if n > m
  107. ;            or else in stk(frame_size + n - m)
  108. ;
  109. ;  * if `CLOSED' is present, reg(nb-arg-regs + 1) contains a pointer to the
  110. ;    closure object
  111. ;
  112. ; for example, if we assume that nb-arg-regs = 3, then after the
  113. ; instruction LABEL(1,2,PROC,5):
  114. ;
  115. ;   reg(0) = return address
  116. ;   stk(1) = parameter 1
  117. ;   stk(2) = parameter 2
  118. ;   reg(1) = parameter 3
  119. ;   reg(2) = parameter 4
  120. ;   reg(3) = parameter 5
  121.  
  122.   (let ((nb-stacked (max 0 (- nb-parms nb-arg-regs))))
  123.  
  124.     (define (location-of-parms i)
  125.       (if (> i nb-parms)
  126.         '()
  127.         (cons (cons i
  128.                     (if (> i nb-stacked)
  129.                       (make-reg (- i nb-stacked))
  130.                       (make-stk i)))
  131.               (location-of-parms (+ i 1)))))
  132.  
  133.     (let ((x (cons (cons 'return 0) (location-of-parms 1))))
  134.       (make-pcontext nb-stacked
  135.         (if closed?
  136.           (cons (cons 'closure-env (make-reg (+ nb-arg-regs 1))) x)
  137.           x)))))
  138.  
  139. (define (jump-info nb-args)
  140.  
  141. ;  * the return address is passed in reg(0)
  142. ;
  143. ;  * if nb-args <= nb-arg-regs,
  144. ;
  145. ;      then, argument `n' is in reg(n)
  146. ;
  147. ;      else, `m' = nb-args - nb-arg-regs arguments are passed
  148. ;            on the stack and argument `n' is in
  149. ;
  150. ;            reg(n - m), if n > m
  151. ;            or else in stk(frame_size + n - m) if n <= m
  152.  
  153.   (let ((nb-stacked (max 0 (- nb-args nb-arg-regs))))
  154.  
  155.     (define (location-of-args i)
  156.       (if (> i nb-args)
  157.         '()
  158.         (cons (cons i
  159.                     (if (> i nb-stacked)
  160.                       (make-reg (- i nb-stacked))
  161.                       (make-stk i)))
  162.               (location-of-args (+ i 1)))))
  163.  
  164.     (make-pcontext nb-stacked
  165.                    (cons (cons 'return (make-reg 0))
  166.                          (location-of-args 1)))))
  167.  
  168. (define (closed-var-offset i)
  169.  
  170. ; a closure looks like:
  171. ;
  172. ;      _____________________
  173. ;     |__length__|___JSR____|          | high
  174. ;     |_____________________| code ptr |
  175. ;     |_____________________| var 1    V
  176. ;     |_____________________| ...
  177. ;     |_____________________| var N
  178. ;      <----- 32 bits ----->
  179.  
  180.   (+ (* i pointer-size) 2))
  181.  
  182. ;------------------------------------------------------------------------------
  183. ;
  184. ; Translation of PVM instructions into target machine instructions:
  185.  
  186. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  187.  
  188. (define (dump proc filename options)
  189.  
  190.   (if *info-port*
  191.     (begin
  192.       (display "Dumping:" *info-port*)
  193.       (newline *info-port*)))
  194.  
  195.   (set! ofile-asm?   (memq 'ASM   options))
  196.   (set! ofile-stats? (memq 'STATS options))
  197.   (set! debug-info?  (memq 'DEBUG options))
  198.  
  199.   (set! object-queue (queue-empty))
  200.   (set! objects-dumped (queue-empty))
  201.  
  202.   (ofile.begin! filename add-object)
  203.  
  204.   (queue-put! object-queue proc)
  205.   (queue-put! objects-dumped proc)
  206.  
  207.   (let loop ((index 0))
  208.     (if (not (queue-empty? object-queue))
  209.       (let ((obj (queue-get! object-queue)))
  210.  
  211.         (dump-object obj index)
  212.  
  213.         (loop (+ index 1)))))
  214.  
  215.   (ofile.end!)
  216.  
  217.   (if *info-port*
  218.     (newline *info-port*))
  219.  
  220.   (set! object-queue '())
  221.   (set! objects-dumped '()))
  222.  
  223. (define debug-info? '())
  224. (define object-queue '())
  225. (define objects-dumped '())
  226.  
  227. ;------------------------------------------------------------------------------
  228.  
  229. (define (add-object obj)
  230.   (if (and (proc-obj? obj) (not (proc-obj-code obj)))
  231.     #f
  232.     (let ((n (pos-in-list obj (queue->list objects-dumped))))
  233.       (if n
  234.         n
  235.         (let ((m (length (queue->list objects-dumped))))
  236.           (queue-put! objects-dumped obj)
  237.           (queue-put! object-queue obj)
  238.           m)))))
  239.  
  240. ;------------------------------------------------------------------------------
  241.  
  242. (define (dump-object obj index)
  243.  
  244.   (ofile-line "|------------------------------------------------------")
  245.  
  246.   (case (obj-type obj)
  247.     ((PAIR)        (dump-PAIR obj))
  248.     ((SUBTYPED)    (case (obj-subtype obj)
  249.                      ((VECTOR) (dump-VECTOR obj))
  250.                      ((SYMBOL) (dump-SYMBOL obj))
  251.                      ((RATNUM) (dump-RATNUM obj))
  252.                      ((CPXNUM) (dump-CPXNUM obj))
  253.                      ((STRING) (dump-STRING obj))
  254.                      ((FLONUM) (dump-FLONUM obj))
  255.                      ((BIGNUM) (dump-BIGNUM obj))
  256.                      (else
  257.                       (compiler-internal-error
  258.                         "dump-object, can't dump object 'obj':" obj))))
  259.     ((PROCEDURE)   (dump-PROCEDURE obj))
  260.     (else
  261.      (compiler-internal-error
  262.        "dump-object, can't dump object 'obj':" obj))))
  263.  
  264. ;------------------------------------------------------------------------------
  265.  
  266. (define (dump-PAIR pair)
  267.   (ofile-long pair-prefix)
  268.   (ofile-ref (cdr pair))
  269.   (ofile-ref (car pair)))
  270.  
  271. ;------------------------------------------------------------------------------
  272.  
  273. (define (dump-VECTOR v)
  274.   (ofile-long (+ (* (vector-length v) #x400) (* subtype-VECTOR 8)))
  275.   (let ((len (vector-length v)))
  276.     (let loop ((i 0))
  277.       (if (< i len)
  278.         (begin
  279.           (ofile-ref (vector-ref v i))
  280.           (loop (+ i 1)))))))
  281.  
  282. ;------------------------------------------------------------------------------
  283.  
  284. (define (dump-SYMBOL sym)
  285.   (compiler-internal-error
  286.     "dump-symbol, can't dump SYMBOL type"))
  287.  
  288. ;------------------------------------------------------------------------------
  289.  
  290. (define (dump-RATNUM x)
  291.   (ofile-long (+ (* 2 #x400) (* subtype-RATNUM 8)))
  292.   (ofile-ref (numerator x))
  293.   (ofile-ref (denominator x)))
  294.  
  295. ;------------------------------------------------------------------------------
  296.  
  297. (define (dump-CPXNUM x)
  298.   (ofile-long (+ (* 2 #x400) (* subtype-CPXNUM 8)))
  299.   (ofile-ref (real-part x))
  300.   (ofile-ref (imag-part x)))
  301.  
  302. ;------------------------------------------------------------------------------
  303.  
  304. (define (dump-STRING s)
  305.   (ofile-long (+ (* (string-length s) #x100) (* subtype-STRING 8)))
  306.   (let ((len (string-length s)))
  307.     (define (ref i) (if (>= i len) 0 (character-encoding (string-ref s i))))
  308.     (let loop ((i 0))
  309.       (if (< i len)
  310.         (begin
  311.           (ofile-word (+ (* (ref i) 256) (ref (+ i 1))))
  312.           (loop (+ i 2)))))))
  313.  
  314. ;------------------------------------------------------------------------------
  315.  
  316. (define (dump-FLONUM x)
  317.   (let ((bits (flonum->bits x)))
  318.     (ofile-long (+ (* 2 #x400) (* subtype-FLONUM 8)))
  319.     (ofile-long (quotient bits #x100000000))
  320.     (ofile-long (modulo   bits #x100000000))))
  321.  
  322. (define (flonum->inexact-exponential-format x)
  323.  
  324.   (define (exp-form-pos x y i)
  325.     (let ((i*2 (+ i i)))
  326.       (let ((z (if (and (not (< flonum-e-bias i*2))
  327.                         (not (< x y)))
  328.                  (exp-form-pos x (* y y) i*2)
  329.                  (cons x 0))))
  330.         (let ((a (car z)) (b (cdr z)))
  331.           (let ((i+b (+ i b)))
  332.             (if (and (not (< flonum-e-bias i+b))
  333.                      (not (< a y)))
  334.               (begin
  335.                 (set-car! z (/ a y))
  336.                 (set-cdr! z i+b)))
  337.             z)))))
  338.  
  339.   (define (exp-form-neg x y i)
  340.     (let ((i*2 (+ i i)))
  341.       (let ((z (if (and (< i*2 flonum-e-bias-minus-1)
  342.                         (< x y))
  343.                  (exp-form-neg x (* y y) i*2)
  344.                  (cons x 0))))
  345.         (let ((a (car z)) (b (cdr z)))
  346.           (let ((i+b (+ i b)))
  347.             (if (and (< i+b flonum-e-bias-minus-1)
  348.                      (< a y))
  349.               (begin
  350.                 (set-car! z (/ a y))
  351.                 (set-cdr! z i+b)))
  352.             z)))))
  353.  
  354.   (define (exp-form x)
  355.     (if (< x inexact-+1)
  356.       (let ((z (exp-form-neg x inexact-+1/2 1)))
  357.         (set-car! z (* inexact-+2 (car z)))
  358.         (set-cdr! z (- -1 (cdr z)))
  359.         z)
  360.       (exp-form-pos x inexact-+2 1)))
  361.  
  362.   (if (negative? x)
  363.     (let ((z (exp-form (- inexact-0 x))))
  364.       (set-car! z (- inexact-0 (car z)))
  365.       z)
  366.     (exp-form x)))
  367.  
  368. (define (flonum->exact-exponential-format x)
  369.   (let ((z (flonum->inexact-exponential-format x)))
  370.     (let ((y (car z)))
  371.       (cond ((not (< y inexact-+2))
  372.              (set-car! z flonum-+m-min)
  373.              (set-cdr! z flonum-e-bias-plus-1))
  374.             ((not (< inexact--2 y))
  375.              (set-car! z flonum--m-min)
  376.              (set-cdr! z flonum-e-bias-plus-1))
  377.             (else
  378.              (set-car! z
  379.                (truncate (inexact->exact (* (car z) inexact-m-min))))))
  380.       (set-cdr! z (- (cdr z) flonum-m-bits))
  381.       z)))
  382.  
  383. (define (flonum->bits x)
  384.  
  385.   (define (bits a b)
  386.     (if (< a flonum-+m-min)
  387.       a
  388.       (+ (- a flonum-+m-min)
  389.          (* (+ (+ b flonum-m-bits) flonum-e-bias)
  390.             flonum-+m-min))))
  391.  
  392.   (let ((z (flonum->exact-exponential-format x)))
  393.     (let ((a (car z)) (b (cdr z)))
  394.       (if (negative? a)
  395.         (+ flonum-sign-bit (bits (- 0 a) b))
  396.         (bits a b)))))
  397.  
  398. (define flonum-m-bits         52)
  399. (define flonum-e-bits         11)
  400. (define flonum-sign-bit       #x8000000000000000) ; (expt 2 (+ flonum-e-bits flonum-m-bits))
  401. (define flonum-+m-min         4503599627370496)   ; (expt 2 flonum-m-bits)
  402. (define flonum--m-min         -4503599627370496)  ; (- flonum-+m-min)
  403. (define flonum-e-bias         1023) ; (- (expt 2 (- flonum-e-bits 1)) 1)
  404. (define flonum-e-bias-plus-1  1024) ; (+ flonum-e-bias 1)
  405. (define flonum-e-bias-minus-1 1022) ; (- flonum-e-bias 1)
  406.  
  407. (define inexact-m-min         (exact->inexact flonum-+m-min))
  408. (define inexact-+2            (exact->inexact 2))
  409. (define inexact--2            (exact->inexact -2))
  410. (define inexact-+1            (exact->inexact 1))
  411. (define inexact-+1/2          (exact->inexact (/ 1 2)))
  412. (define inexact-0             (exact->inexact 0))
  413.  
  414. ;------------------------------------------------------------------------------
  415.  
  416. (define (dump-BIGNUM x)
  417.  
  418.   (define radix 16384)
  419.  
  420.   (define (integer->digits n)
  421.     (if (= n 0)
  422.       '()
  423.       (cons (remainder n radix)
  424.             (integer->digits (quotient n radix)))))
  425.  
  426.   (let ((l (integer->digits (abs x))))
  427.  
  428.     (ofile-long (+ (* (+ (length l) 1) #x200) (* subtype-BIGNUM 8)))
  429.  
  430.     (if (< x 0)
  431.       (ofile-word 0)
  432.       (ofile-word 1))
  433.  
  434.     (for-each ofile-word l)))
  435.  
  436. ;------------------------------------------------------------------------------
  437.  
  438. (define (dump-PROCEDURE proc)
  439.   (let ((bbs (proc-obj-code proc)))
  440.  
  441.     (set! entry-lbl-num (bbs-entry-lbl-num bbs))
  442.     (set! label-counter (bbs-lbl-counter bbs))
  443.     (set! var-descr-queue (queue-empty))
  444.     (set! first-class-label-queue (queue-empty))
  445.     (set! deferred-code-queue (queue-empty))
  446.  
  447.     (if *info-port*
  448.       (begin
  449.         (display "  #[" *info-port*)
  450.         (if (proc-obj-primitive? proc)
  451.           (display "primitive " *info-port*)
  452.           (display "procedure " *info-port*))
  453.         (display (proc-obj-name proc) *info-port*)
  454.         (display "]" *info-port*)))
  455.  
  456.     (if (proc-obj-primitive? proc)
  457.       (ofile-prim-proc (proc-obj-name proc))
  458.       (ofile-user-proc))
  459.  
  460.     (asm.begin!)
  461.  
  462.     (let loop ((prev-bb #f)
  463.                (prev-pvm-instr #f)
  464.                (l (bbs->code-list bbs)))
  465.       (if (not (null? l))
  466.         (let ((pres-bb (code-bb (car l)))
  467.               (pres-pvm-instr (code-pvm-instr (car l)))
  468.               (pres-slots-needed (code-slots-needed (car l)))
  469.               (next-pvm-instr (if (null? (cdr l))
  470.                                 #f
  471.                                 (code-pvm-instr (cadr l)))))
  472.  
  473.           (if ofile-asm? (asm-comment (car l)))
  474.  
  475.           (gen-pvm-instr prev-pvm-instr
  476.                          pres-pvm-instr
  477.                          next-pvm-instr
  478.                          pres-slots-needed)
  479.  
  480.           (loop pres-bb pres-pvm-instr (cdr l)))))
  481.  
  482.     (asm.end!
  483.       (if debug-info?
  484.         (vector (lst->vector (queue->list first-class-label-queue))
  485.                 (lst->vector (queue->list var-descr-queue)))
  486.         #f))
  487.  
  488.     (if *info-port*
  489.       (newline *info-port*))
  490.  
  491.     (set! var-descr-queue '())
  492.     (set! first-class-label-queue '())
  493.     (set! deferred-code-queue '())
  494.     (set! instr-source '())
  495.     (set! entry-frame '())
  496.     (set! exit-frame '())))
  497.  
  498. (define label-counter '())
  499. (define entry-lbl-num '())
  500. (define var-descr-queue '())
  501. (define first-class-label-queue '())
  502. (define deferred-code-queue '())
  503. (define instr-source '())
  504. (define entry-frame '())
  505. (define exit-frame '())
  506.  
  507. (define (defer-code! thunk)
  508.   (queue-put! deferred-code-queue thunk))
  509.  
  510. (define (gen-deferred-code!)
  511.   (let loop ()
  512.     (if (not (queue-empty? deferred-code-queue))
  513.       (let ((thunk (queue-get! deferred-code-queue)))
  514.         (thunk)
  515.         (loop)))))
  516.  
  517. (define (add-var-descr! descr)
  518.  
  519.   (define (index x l)
  520.     (let loop ((l l) (i 0))
  521.       (cond ((not (pair? l))    #f)
  522.             ((equal? (car l) x) i)
  523.             (else               (loop (cdr l) (+ i 1))))))
  524.  
  525.   (let ((n (index descr (queue->list var-descr-queue))))
  526.     (if n
  527.       n
  528.       (let ((m (length (queue->list var-descr-queue))))
  529.         (queue-put! var-descr-queue descr)
  530.         m))))
  531.  
  532. (define (add-first-class-label! source slots frame)
  533.   (let loop ((i 0) (l1 slots) (l2 '()))
  534.     (if (pair? l1)
  535.       (let ((var (car l1)))
  536.         (let ((x (frame-live? var frame)))
  537.           (if (and x (or (pair? x) (not (temp-var? x))))
  538.             (let ((descr-index
  539.                     (add-var-descr!
  540.                      (if (pair? x)
  541.                         (map (lambda (y) (add-var-descr! (var-name y))) x)
  542.                         (var-name x)))))
  543.               (loop (+ i 1) (cdr l1) (cons (+ (* i 16384) descr-index) l2)))
  544.             (loop (+ i 1) (cdr l1) l2))))
  545.       (let ((label-descr (lst->vector (cons 0 (cons source l2)))))
  546.         (queue-put! first-class-label-queue label-descr)
  547.         label-descr))))
  548.  
  549. (define (gen-pvm-instr prev-pvm-instr pvm-instr next-pvm-instr sn)
  550.  
  551.   (set! instr-source (comment-get (pvm-instr-comment pvm-instr) 'SOURCE))
  552.   (set! exit-frame   (pvm-instr-frame pvm-instr))
  553.   (set! entry-frame  (and prev-pvm-instr (pvm-instr-frame prev-pvm-instr)))
  554.  
  555.   (case (pvm-instr-type pvm-instr)
  556.  
  557.     ((LABEL)
  558.      (set! entry-frame exit-frame)
  559.      (set! current-fs (frame-size exit-frame))
  560.      (case (LABEL-type pvm-instr)
  561.        ((SIMP)
  562.         (gen-LABEL-SIMP (LABEL-lbl-num pvm-instr)
  563.                         sn))
  564.        ((TASK)
  565.         (gen-LABEL-TASK (LABEL-lbl-num pvm-instr)
  566.                         (LABEL-TASK-method pvm-instr)
  567.                         sn))
  568.        ((PROC)
  569.         (gen-LABEL-PROC (LABEL-lbl-num pvm-instr)
  570.                         (LABEL-PROC-nb-parms pvm-instr)
  571.                         (LABEL-PROC-min pvm-instr)
  572.                         (LABEL-PROC-rest? pvm-instr)
  573.                         (LABEL-PROC-closed? pvm-instr)
  574.                         sn))
  575.        ((RETURN)
  576.         (gen-LABEL-RETURN (LABEL-lbl-num pvm-instr)
  577.                           (LABEL-RETURN-task-method pvm-instr)
  578.                           sn))
  579.        (else
  580.         (compiler-internal-error
  581.           "gen-pvm-instr, unknown label type"))))
  582.  
  583.     ((APPLY)
  584.      (gen-APPLY (APPLY-prim pvm-instr)
  585.                 (APPLY-opnds pvm-instr)
  586.                 (APPLY-loc pvm-instr)
  587.                 sn))
  588.  
  589.     ((COPY)
  590.      (gen-COPY (COPY-opnd pvm-instr)
  591.                (COPY-loc pvm-instr)
  592.                sn))
  593.  
  594.     ((MAKE_CLOSURES)
  595.      (gen-MAKE_CLOSURES (MAKE_CLOSURES-parms pvm-instr)
  596.                         sn))
  597.  
  598.     ((COND)
  599.      (gen-COND (COND-test pvm-instr)
  600.                (COND-opnds pvm-instr)
  601.                (COND-true pvm-instr)
  602.                (COND-false pvm-instr)
  603.                (COND-intr-check? pvm-instr)
  604.                (if (and next-pvm-instr
  605.                         (memq (LABEL-type next-pvm-instr) '(SIMP TASK)))
  606.                  (LABEL-lbl-num next-pvm-instr)
  607.                  #f)))
  608.  
  609.     ((JUMP)
  610.      (gen-JUMP (JUMP-opnd pvm-instr)
  611.                (JUMP-nb-args pvm-instr)
  612.                (JUMP-intr-check? pvm-instr)
  613.                (if (and next-pvm-instr
  614.                         (memq (LABEL-type next-pvm-instr) '(SIMP TASK)))
  615.                  (LABEL-lbl-num next-pvm-instr)
  616.                  #f)))
  617.  
  618.     (else
  619.      (compiler-internal-error
  620.        "gen-pvm-instr, unknown 'pvm-instr':"
  621.        pvm-instr))))
  622.  
  623.  
  624. ;------------------------------------------------------------------------------
  625. ;
  626. ; Useful tools:
  627.  
  628. (define (reg-in-opnd68 opnd) ; return the register used in an operand
  629.   (cond ((dreg? opnd) opnd)
  630.         ((areg? opnd) opnd)
  631.         ((ind? opnd)  (ind-areg opnd))
  632.         ((pinc? opnd) (pinc-areg opnd))
  633.         ((pdec? opnd) (pdec-areg opnd))
  634.         ((disp? opnd) (disp-areg opnd))
  635.         ((inx? opnd)  (inx-ireg opnd)) ; disregard address register
  636.         (else         #f)))
  637.  
  638. (define (temp-in-opnd68 opnd) ; return the temporary reg used in an operand
  639.   (let ((reg (reg-in-opnd68 opnd)))
  640.     (if reg
  641.       (cond ((identical-opnd68? reg dtemp1) reg)
  642.             ((identical-opnd68? reg atemp1) reg)
  643.             ((identical-opnd68? reg atemp2) reg)
  644.             (else                           #f))
  645.       #f)))
  646.  
  647. (define (pick-atemp keep) ; return a temp address reg different from 'keep'
  648.   (if (and keep (identical-opnd68? keep atemp1))
  649.     atemp2
  650.     atemp1))
  651.  
  652. (define return-reg '())
  653.  
  654. ; structures:
  655.  
  656. (define max-nb-args           1024)
  657.  
  658. (define heap-allocation-fudge (* pointer-size (+ (* 2 max-nb-args) 1024)))
  659.  
  660. (define intr-flag             0)
  661. (define ltq-tail              1)
  662. (define ltq-head              2)
  663. (define heap-lim              12)
  664. (define closure-lim           17)
  665. (define closure-ptr           18)
  666. (define workq-head            22)
  667.  
  668. (define intr-flag-slot   (make-disp* pstate-reg (* pointer-size intr-flag)))
  669. (define ltq-tail-slot    (make-disp* pstate-reg (* pointer-size ltq-tail)))
  670. (define ltq-head-slot    (make-disp* pstate-reg (* pointer-size ltq-head)))
  671. (define heap-lim-slot    (make-disp* pstate-reg (* pointer-size heap-lim)))
  672. (define closure-lim-slot (make-disp* pstate-reg (* pointer-size closure-lim)))
  673. (define closure-ptr-slot (make-disp* pstate-reg (* pointer-size closure-ptr)))
  674. (define workq-head-slot  (make-disp* pstate-reg (* pointer-size workq-head)))
  675.  
  676. (define TOUCH-trap                1)
  677. (define non-proc-jump-trap        6)
  678. (define rest-params-trap          7)
  679. (define rest-params-closed-trap   8)
  680. (define wrong-nb-arg1-trap        9)
  681. (define wrong-nb-arg1-closed-trap 10)
  682. (define wrong-nb-arg2-trap        11)
  683. (define wrong-nb-arg2-closed-trap 12)
  684. (define heap-alloc1-trap          13)
  685. (define heap-alloc2-trap          14)
  686. (define closure-alloc-trap        15)
  687. (define delay-future-trap         16)
  688. (define eager-future-trap         17)
  689. (define steal-conflict-trap       18)
  690. (define intr-trap                 24)
  691.  
  692. (define cache-line-length         16) ; works on 68020/68030/68040
  693.  
  694. (define intr-latency '())
  695. (set! intr-latency                10) ; controls interrupt latency
  696.  
  697. (define lazy-task-kind '())
  698. (set! lazy-task-kind              'MESSAGE-PASSING-LTQ) ; what kind of LTC
  699.  
  700. ;------------------------------------------------------------------------------
  701.  
  702. (define (stat-clear!)
  703.   (set! *stats* (cons 0 '())))
  704.  
  705. (define (stat-dump!)
  706.   (emit-stat (cdr *stats*)))
  707.  
  708. (define (stat-add! bin count)
  709.  
  710.   (define (add! stats bin count)
  711.     (set-car! stats (+ (car stats) count))
  712.     (if (not (null? bin))
  713.       (let ((x (assoc (car bin) (cdr stats))))
  714.         (if x
  715.           (add! (cdr x) (cdr bin) count)
  716.           (begin
  717.             (set-cdr! stats (cons (list (car bin) 0) (cdr stats)))
  718.             (add! (cdadr stats) (cdr bin) count))))))
  719.  
  720.   (add! *stats* bin count))
  721.  
  722. (define (fetch-stat-add! pvm-opnd)
  723.   (opnd-stat-add! 'fetch pvm-opnd))
  724.  
  725. (define (store-stat-add! pvm-opnd)
  726.   (opnd-stat-add! 'store pvm-opnd))
  727.  
  728. (define (jump-stat-add! pvm-opnd)
  729.   (opnd-stat-add! 'jump pvm-opnd))
  730.  
  731. (define (opnd-stat-add! type opnd)
  732.   (cond ((reg? opnd)
  733.          (stat-add! (list 'pvm-opnd 'reg type (reg-num opnd)) 1))
  734.         ((stk? opnd)
  735.          (stat-add! (list 'pvm-opnd 'stk type) 1))
  736.         ((glo? opnd)
  737.          (stat-add! (list 'pvm-opnd 'glo type (glo-name opnd)) 1))
  738.         ((clo? opnd)
  739.          (stat-add! (list 'pvm-opnd 'clo type) 1)
  740.          (fetch-stat-add! (clo-base opnd)))
  741.         ((lbl? opnd)
  742.          (stat-add! (list 'pvm-opnd 'lbl type) 1))
  743.         ((obj? opnd)
  744.          (let ((val (obj-val opnd)))
  745.            (if (number? val)
  746.              (stat-add! (list 'pvm-opnd 'obj type val) 1)
  747.              (stat-add! (list 'pvm-opnd 'obj type (obj-type val)) 1))))
  748.         (else
  749.          (compiler-internal-error
  750.            "opnd-stat-add!, unknown 'opnd':" opnd))))
  751.  
  752. (define (opnd-stat opnd)
  753.   (cond ((reg? opnd) 'reg)
  754.         ((stk? opnd) 'stk)
  755.         ((glo? opnd) 'glo)
  756.         ((clo? opnd) 'clo)
  757.         ((lbl? opnd) 'lbl)
  758.         ((obj? opnd) 'obj)
  759.         (else
  760.          (compiler-internal-error
  761.            "opnd-stat, unknown 'opnd':" opnd))))
  762.  
  763. (define *stats* '())
  764.  
  765. ;------------------------------------------------------------------------------
  766.  
  767. (define (move-opnd68-to-loc68 opnd loc)
  768.   (if (not (identical-opnd68? opnd loc))
  769.     (if (imm? opnd)
  770.       (move-n-to-loc68 (imm-val opnd) loc)
  771.       (emit-move.l opnd loc))))
  772.  
  773. (define (move-obj-to-loc68 obj loc)
  774.   (let ((n (obj-encoding obj)))
  775.     (if n
  776.       (move-n-to-loc68 n loc)
  777.       (emit-move.l (emit-const obj) loc))))
  778.  
  779. (define (move-n-to-loc68 n loc)
  780.   (cond ((= n bits-NULL)
  781.          (emit-move.l null-reg loc))
  782.         ((= n bits-FALSE)
  783.          (emit-move.l false-reg loc))
  784.         ((and (dreg? loc) (>= n -128) (<= n 127))
  785.          (emit-moveq n loc))
  786.         ((and (areg? loc) (>= n -32768) (<= n 32767))
  787.          (emit-move.w (make-imm n) loc))
  788.         ((and (areg? loc) (>= n 0) (<= n 65535))
  789.          (emit-lea* n loc))
  790.         ((and (identical-opnd68? loc pdec-sp) (>= n 0) (<= n 65535))
  791.          (emit-pea* n))
  792.         ((= n 0)
  793.          (emit-clr.l loc))
  794.         ((and (not (and (inx? loc) (= (inx-ireg loc) dtemp1))) (>= n -128) (<= n 127))
  795.          (emit-moveq n dtemp1)
  796.          (emit-move.l dtemp1 loc))
  797.         (else
  798.          (emit-move.l (make-imm n) loc))))
  799.  
  800. (define (add-n-to-loc68 n loc)
  801.   (if (not (= n 0))
  802.     (cond ((and (>= n -8) (<= n 8))
  803.            (if (> n 0) (emit-addq.l n loc) (emit-subq.l (- n) loc)))
  804.           ((and (areg? loc) (>= n -32768) (<= n 32767))
  805.            (emit-lea (make-disp loc n) loc))
  806.           ((and (not (identical-opnd68? loc dtemp1)) (>= n -128) (<= n 128))
  807.            (emit-moveq (- (abs n)) dtemp1)
  808.            (if (> n 0) (emit-sub.l dtemp1 loc) (emit-add.l dtemp1 loc)))
  809.           (else
  810.            (emit-add.l (make-imm n) loc)))))
  811.  
  812. (define (power-of-2 n)
  813.   (let loop ((i 0) (k 1))
  814.     (cond ((= k n) i)
  815.           ((> k n) #f)
  816.           (else    (loop (+ i 1) (* k 2))))))
  817.  
  818. (define (mul-n-to-reg68 n reg)
  819.   (if (= n 0)
  820.     (emit-moveq 0 reg)
  821.     (let ((abs-n (abs n)))
  822.       (if (= abs-n 1)
  823.         (if (< n 0) (emit-neg.l reg))
  824.         (let ((shift (power-of-2 abs-n)))
  825.           (if shift
  826.             (let ((m (min shift 32)))
  827.               (if (or (<= m 8) (identical-opnd68? reg dtemp1))
  828.                 (let loop ((i m))
  829.                   (if (> i 0)
  830.                     (begin (emit-asl.l (make-imm (min i 8)) reg) (loop (- i 8)))))
  831.                 (begin
  832.                   (emit-moveq m dtemp1)
  833.                   (emit-asl.l dtemp1 reg)))
  834.               (if (< n 0) (emit-neg.l reg)))
  835.             (emit-muls.l (make-imm n) reg)))))))
  836.  
  837. (define (div-n-to-reg68 n reg)
  838.   (let ((abs-n (abs n)))
  839.     (if (= abs-n 1)
  840.       (if (< n 0) (emit-neg.l reg))
  841.       (let ((shift (power-of-2 abs-n)))
  842.         (if shift
  843.           (let ((m (min shift 32))
  844.                 (lbl (new-lbl!)))
  845.             (emit-move.l reg reg)
  846.             (emit-bpl lbl)
  847.             (add-n-to-loc68 (* (- abs-n 1) 8) reg)
  848.             (emit-label lbl)
  849.             (if (or (<= m 8) (identical-opnd68? reg dtemp1))
  850.               (let loop ((i m))
  851.                 (if (> i 0)
  852.                   (begin (emit-asr.l (make-imm (min i 8)) reg) (loop (- i 8)))))
  853.               (begin
  854.                 (emit-moveq m dtemp1)
  855.                 (emit-asr.l dtemp1 reg)))
  856.             (if (< n 0) (emit-neg.l reg)))
  857.           (emit-divsl.l (make-imm n) reg reg))))))
  858.  
  859. (define (cmp-n-to-opnd68 n opnd)
  860.   (cond ((= n bits-NULL)
  861.          (emit-cmp.l opnd null-reg)
  862.          #f)
  863.         ((= n bits-FALSE)
  864.          (emit-cmp.l opnd false-reg)
  865.          #f)
  866.         ((or (pcr? opnd) (imm? opnd))
  867.          (if (= n 0)
  868.            (begin
  869.              (emit-move.l opnd dtemp1)
  870.              #t)
  871.            (begin
  872.              (move-opnd68-to-loc68 opnd atemp1)
  873.              (if (and (>= n -32768) (<= n 32767))
  874.                (emit-cmp.w (make-imm n) atemp1)
  875.                (emit-cmp.l (make-imm n) atemp1))
  876.              #t)))
  877.         ((= n 0)
  878.          (emit-move.l opnd dtemp1)
  879.          #t)
  880.         ((and (>= n -128) (<= n 127) (not (identical-opnd68? opnd dtemp1)))
  881.          (emit-moveq n dtemp1)
  882.          (emit-cmp.l opnd dtemp1)
  883.          #f)
  884.         (else
  885.          (emit-cmp.l (make-imm n) opnd)
  886.          #t)))
  887.  
  888. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  889.  
  890. (define (might-touch-opnd? opnd)
  891.   (cond ((pot-fut? opnd)
  892.          #t)
  893.         ((clo? opnd)
  894.          (might-touch-opnd? (clo-base opnd)))
  895.         (else
  896.          #f)))
  897.  
  898. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  899.  
  900. ; current-fs is the current frame size.
  901.  
  902. (define current-fs '())
  903.  
  904. ; (adjust-current-fs n) adds 'n' to the current frame size.
  905.  
  906. (define (adjust-current-fs n)
  907.   (set! current-fs (+ current-fs n)))
  908.  
  909. ; (new-lbl!) returns a new label number different from all others in this
  910. ; procedure.
  911.  
  912. (define (new-lbl!)
  913.   (label-counter))
  914.  
  915. ; (needed? loc sn) is false if we are sure that the location 'loc' is not
  916. ; needed (assuming that only 'sn' slots on the stack are needed).
  917.  
  918. (define (needed? loc sn)
  919.   (and loc (if (stk? loc) (<= (stk-num loc) sn) #t)))
  920.  
  921. ; (sn-opnd opnd sn) returns the number of slots that are needed in the
  922. ; stack frame to reference 'opnd'.  'sn' is the number of slots that must be
  923. ; preserved in the frame.
  924.  
  925. (define (sn-opnd opnd sn)
  926.   (cond ((stk? opnd)
  927.          (max (stk-num opnd) sn))
  928.         ((clo? opnd)
  929.          (sn-opnd (clo-base opnd) sn))
  930.         (else
  931.          sn)))
  932.  
  933. ; (sn-opnds opnds sn) returns the number of slots that are needed in the
  934. ; stack frame to reference all of the operands in 'opnds'.  'sn' is the number
  935. ; of slots that must be preserved in the frame.
  936.  
  937. (define (sn-opnds opnds sn)
  938.   (if (null? opnds)
  939.     sn
  940.     (sn-opnd (car opnds) (sn-opnds (cdr opnds) sn))))
  941.  
  942. ; (sn-opnd68 opnd sn) is similar to 'sn-opnd' except that it works with
  943. ; M68000 operands.
  944.  
  945. (define (sn-opnd68 opnd sn)
  946.   (cond ((and (disp*? opnd) (identical-opnd68? (disp*-areg opnd) sp-reg))
  947.          (max (disp*-offset opnd) sn))
  948.         ((identical-opnd68? opnd pdec-sp)
  949.          (max (+ current-fs 1) sn))
  950.         ((identical-opnd68? opnd pinc-sp)
  951.          (max current-fs sn))
  952.         (else
  953.          sn)))
  954.  
  955. ; (resize-frame n) generates the code to move the stack pointer to
  956. ; frame slot number 'n'.
  957.  
  958. (define (resize-frame n)
  959.   (let ((x (- n current-fs)))
  960.     (adjust-current-fs x)
  961.     (add-n-to-loc68 (* (- pointer-size) x) sp-reg)))
  962.  
  963. ; (shrink-frame n) generates the code to resize the frame to leave
  964. ; only the first 'n' slots on the stack.
  965.  
  966. (define (shrink-frame n)
  967.   (cond ((< n current-fs)
  968.          (resize-frame n))
  969.         ((> n current-fs)
  970.          (compiler-internal-error "shrink-frame, can't increase frame size"))))
  971.  
  972. ; (make-top-of-frame n sn) generates the code to resize the frame so that
  973. ; slot 'n' is on top of the stack while leaving at least 'sn' slots
  974. ; in the frame.
  975.  
  976. (define (make-top-of-frame n sn)
  977.   (if (and (< n current-fs) (>= n sn)) (resize-frame n)))
  978.  
  979. ; (make-top-of-frame-if-stk-opnd68 opnd sn) generates the code to resize the
  980. ; frame so that a subsequent reference to 'opnd' (if it is a stack slot) will
  981. ; be easier.  'sn' is the number of slots that must be preserved in the
  982. ; frame (the stack frame might be shrunk down to that size).
  983.  
  984. (define (make-top-of-frame-if-stk-opnd68 opnd sn)
  985.   (if (frame-base-rel? opnd)
  986.     (make-top-of-frame (frame-base-rel-slot opnd) sn)))
  987.  
  988. ; (make-top-of-frame-if-stk-opnds68 opnd1 opnd2 sn) generates the code to resize
  989. ; the frame so that subsequent references to 'opnd1' and 'opnd2' (if they are
  990. ; stack slots) will be easier.  'sn' is the number of slots that must be
  991. ; preserved in the frame (the stack frame might be shrunk down to that size).
  992.  
  993. (define (make-top-of-frame-if-stk-opnds68 opnd1 opnd2 sn)
  994.   (if (frame-base-rel? opnd1)
  995.     (let ((slot1 (frame-base-rel-slot opnd1)))
  996.       (if (frame-base-rel? opnd2)
  997.         (make-top-of-frame (max (frame-base-rel-slot opnd2) slot1) sn)
  998.         (make-top-of-frame slot1 sn)))
  999.     (if (frame-base-rel? opnd2)
  1000.       (make-top-of-frame (frame-base-rel-slot opnd2) sn))))
  1001.  
  1002. ; (opnd68->true-opnd68 opnd sn) transforms 'frame base relative' stack operands
  1003. ; into 'top of stack relative' stack operands (as they must appear to the
  1004. ; processor).  'push' or 'pop' operands are returned when possible.  All
  1005. ; other operands are already correct so they are simply returned unchanged.
  1006.  
  1007. (define (opnd68->true-opnd68 opnd sn)
  1008.   (if (frame-base-rel? opnd)
  1009.     (let ((slot (frame-base-rel-slot opnd)))
  1010.  
  1011.       (cond ((> slot current-fs) ; push?
  1012.              (adjust-current-fs 1)
  1013.              pdec-sp)             
  1014.  
  1015.             ((and (= slot current-fs) (< sn current-fs)) ; pop?
  1016.              (adjust-current-fs -1)
  1017.              pinc-sp)
  1018.  
  1019.             (else
  1020.              (make-disp* sp-reg (* pointer-size (- current-fs slot))))))
  1021.  
  1022.     opnd))
  1023.  
  1024. ; (move-opnd68-to-any-areg opnd keep sn) generates the code to move the value
  1025. ; from a M68000 operand to any address register.  'keep' (if not #f) is a
  1026. ; M68000 register that must not be modified.
  1027.  
  1028. (define (move-opnd68-to-any-areg opnd keep sn)
  1029.   (if (areg? opnd)
  1030.     opnd
  1031.     (let ((areg (pick-atemp keep)))
  1032.       (make-top-of-frame-if-stk-opnd68 opnd sn)
  1033.       (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn) areg)
  1034.       areg)))
  1035.  
  1036. ; (clo->opnd68 opnd keep sn) returns the M68000 operand corresponding
  1037. ; to the PVM closed operand 'opnd'.  'keep' (if not #f) is a M68000
  1038. ; register that must not be modified.  Code might be generated in the
  1039. ; process (to load the base in an address register and/or to touch
  1040. ; the base if it is a touch operand).
  1041.  
  1042. (define (clo->opnd68 opnd keep sn)
  1043.   (let ((base (clo-base opnd))
  1044.         (offs (closed-var-offset (clo-index opnd))))
  1045.     (if (lbl? base)
  1046.       (make-pcr (lbl-num base) offs)
  1047.       (clo->loc68 opnd keep sn))))
  1048.  
  1049. ; (clo->loc68 opnd keep sn) is similar in function to 'clo->opnd68' except
  1050. ; that a 'data alterable' addressing mode operand is returned.
  1051.  
  1052. (define (clo->loc68 opnd keep sn)
  1053.   (let ((base (clo-base opnd))
  1054.         (offs (closed-var-offset (clo-index opnd))))
  1055.  
  1056.     (cond ((eq? base return-reg)
  1057.            (make-disp* (reg->reg68 base) offs))
  1058.  
  1059.           ((obj? base)
  1060.            (let ((areg (pick-atemp keep)))
  1061.              (move-obj-to-loc68 (obj-val base) areg)
  1062.              (make-disp* areg offs)))
  1063.  
  1064.           ((pot-fut? base)
  1065.            (let ((reg (touch-opnd-to-any-reg68 base keep sn)))
  1066.              (make-disp* (move-opnd68-to-any-areg reg keep sn) offs)))
  1067.  
  1068.           (else
  1069.            (let ((areg (pick-atemp keep)))
  1070.              (move-opnd-to-loc68 base areg sn)
  1071.              (make-disp* areg offs))))))
  1072.  
  1073. ; (reg->reg68 reg) returns the M68000 register corresponding to the PVM
  1074. ; register 'reg'.
  1075.  
  1076. (define (reg->reg68 reg)
  1077.   (reg-num->reg68 (reg-num reg)))
  1078.  
  1079. (define (reg-num->reg68 num)
  1080.   (if (= num 0) (make-areg pvm-reg0) (make-dreg (+ (- num 1) pvm-reg1))))
  1081.  
  1082. ; (opnd->opnd68 opnd keep sn) returns the M68000 operand corresponding
  1083. ; to the PVM operand 'opnd'.  'keep' (if not #f) is a M68000
  1084. ; register that must not be modified.  Code might be generated in the
  1085. ; process (to load the base in an address register and/or to touch
  1086. ; the base if it is a touch operand).
  1087.  
  1088. (define (opnd->opnd68 opnd keep sn)
  1089.   (cond ((lbl? opnd)
  1090.          (let ((areg (pick-atemp keep)))
  1091.            (emit-lea (make-pcr (lbl-num opnd) 0) areg)
  1092.            areg))
  1093.  
  1094.         ((obj? opnd)
  1095.          (let ((val (obj-val opnd)))
  1096.            (if (proc-obj? val)
  1097.              (let ((num (add-object val))
  1098.                    (areg (pick-atemp keep)))
  1099.                (if num
  1100.                  (emit-move-proc num areg)
  1101.                  (emit-move-prim val areg))
  1102.                areg)
  1103.              (let ((n (obj-encoding val)))
  1104.                (if n
  1105.                  (make-imm n)
  1106.                  (emit-const val))))))
  1107.  
  1108.         ((clo? opnd)
  1109.          (clo->opnd68 opnd keep sn))
  1110.  
  1111.         (else
  1112.          (loc->loc68 opnd keep sn))))
  1113.  
  1114. ; (loc->loc68 loc keep sn) returns the M68000 'data alterable' addressing
  1115. ; mode operand corresponding to the PVM location 'loc'.  'keep' (if not #f)
  1116. ; is a M68000 register that must not be modified.  Code might be generated
  1117. ; in the process (to load the base in an address register and/or to touch
  1118. ; the base if it is a touch operand).
  1119.  
  1120. (define (loc->loc68 loc keep sn)
  1121.  
  1122.   (cond ((reg? loc)
  1123.          (reg->reg68 loc))
  1124.  
  1125.         ((stk? loc)
  1126.          (make-frame-base-rel (stk-num loc)))
  1127.          ; will be converted later by 'opnd68->true-opnd68'
  1128.  
  1129.         ((glo? loc)
  1130.          (make-glob (glo-name loc)))
  1131.  
  1132.         ((clo? loc)
  1133.          (clo->loc68 loc keep sn))
  1134.  
  1135.         (else
  1136.          (compiler-internal-error
  1137.            "loc->loc68, unknown 'loc':" loc))))
  1138.  
  1139. ; (move-opnd68-to-loc opnd loc sn) generates the code to move a
  1140. ; M68000 operand into a PVM location.  'sn' is the number of slots that
  1141. ; must be preserved in the frame (the stack frame might be shrunk down
  1142. ; to that size).
  1143.  
  1144. (define (move-opnd68-to-loc opnd loc sn)
  1145.  
  1146.   (cond ((reg? loc)
  1147.          (make-top-of-frame-if-stk-opnd68 opnd sn)
  1148.          (move-opnd68-to-loc68
  1149.            (opnd68->true-opnd68 opnd sn)
  1150.            (reg->reg68 loc)))
  1151.  
  1152.         ((stk? loc)
  1153.          (let* ((loc-slot (stk-num loc))
  1154.                 (sn-after-opnd1 (if (< loc-slot sn) sn (- loc-slot 1))))
  1155.            (if (> current-fs loc-slot)
  1156.              (make-top-of-frame
  1157.                (if (frame-base-rel? opnd)
  1158.                  (let ((opnd-slot (frame-base-rel-slot opnd)))
  1159.                    (if (>= opnd-slot (- loc-slot 1)) opnd-slot loc-slot))
  1160.                  loc-slot)
  1161.                sn-after-opnd1))
  1162.            (let* ((opnd1 (opnd68->true-opnd68 opnd sn-after-opnd1))
  1163.                   (opnd2 (opnd68->true-opnd68 (make-frame-base-rel loc-slot) sn)))
  1164.              (move-opnd68-to-loc68 opnd1 opnd2))))
  1165.  
  1166.         ((glo? loc)
  1167.          (make-top-of-frame-if-stk-opnd68 opnd sn)
  1168.          (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn)
  1169.                                (make-glob (glo-name loc))))
  1170.  
  1171.         ((clo? loc)
  1172.          (let ((clo (clo->loc68
  1173.                       loc
  1174.                       (temp-in-opnd68 opnd)
  1175.                       (sn-opnd68 opnd sn))))
  1176.            (make-top-of-frame-if-stk-opnd68 opnd sn)
  1177.            (move-opnd68-to-loc68
  1178.              (opnd68->true-opnd68 opnd sn)
  1179.              clo)))
  1180.  
  1181.         (else
  1182.          (compiler-internal-error
  1183.            "move-opnd68-to-loc, unknown 'loc':" loc))))
  1184.  
  1185. ; (move-opnd-to-loc68 opnd loc68 sn) generates the code to copy the value
  1186. ; from PVM operand 'opnd' to the M68000 location 'loc68'.
  1187.  
  1188. (define (move-opnd-to-loc68 opnd loc68 sn)
  1189.   (if (and (lbl? opnd) (areg? loc68))
  1190.  
  1191.     (emit-lea (make-pcr (lbl-num opnd) 0) loc68)
  1192.  
  1193.     (let* ((sn-after-opnd68 (sn-opnd68 loc68 sn))
  1194.            (opnd68 (opnd->opnd68 opnd (temp-in-opnd68 loc68) sn-after-opnd68)))
  1195.       (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn)
  1196.       (let* ((opnd68* (opnd68->true-opnd68 opnd68 sn-after-opnd68))
  1197.              (loc68* (opnd68->true-opnd68 loc68 sn)))
  1198.         (move-opnd68-to-loc68 opnd68* loc68*)))))
  1199.  
  1200. ; (touch-reg68-to-reg68 src dst keep) generates the code to touch the
  1201. ; M68000 register 'src' and put the result in the M68000 register 'dst'.
  1202. ; 'keep' (if not #f) is a M68000 register that must not be modified.
  1203.  
  1204. (define (touch-reg68-to-reg68 src dst keep)
  1205.  
  1206.   (define (trap-to-touch-handler dreg keep lbl)
  1207.     (if ofile-stats?
  1208.       (emit-stat '((touch 0 (determined-placeholder -1)
  1209.                             (undetermined-placeholder 1)))))
  1210.     (if keep (begin (emit-move.l keep pdec-sp) (adjust-current-fs 1)))
  1211.     (gen-trap instr-source entry-frame #t dreg (+ TOUCH-trap (dreg-num dreg)) lbl)
  1212.     (if keep (begin (emit-move.l pinc-sp keep) (adjust-current-fs -1))))
  1213.  
  1214.   (define (touch-dreg-to-reg src dst keep)
  1215.     (let ((lbl1 (new-lbl!))
  1216. ;          (lbl2 (new-lbl!))
  1217.           (areg (pick-atemp keep)))
  1218.       (emit-btst   src placeholder-reg)
  1219.       (emit-bne    lbl1)
  1220.       (if ofile-stats?
  1221.         (emit-stat '((touch 0 (non-placeholder -1)
  1222.                               (determined-placeholder 1)))))
  1223. ;      (emit-move.l src areg)
  1224. ;      (emit-move.l (make-disp* areg (- type-PLACEHOLDER)) dst)
  1225. ;      (emit-cmp.l  dst (if (dreg? dst) areg src))
  1226. ;      (emit-bne    lbl2)
  1227.       (trap-to-touch-handler src keep lbl1)
  1228.       (move-opnd68-to-loc68 src dst)
  1229. ;      (emit-label  lbl2)
  1230. ))
  1231.  
  1232.   (define (touch-areg-to-dreg src dst keep)
  1233.     (let ((lbl1 (new-lbl!)))
  1234.       (emit-move.l src dst)
  1235.       (emit-btst   dst placeholder-reg)
  1236.       (emit-bne    lbl1)
  1237.       (if ofile-stats?
  1238.         (emit-stat '((touch 0 (non-placeholder -1)
  1239.                               (determined-placeholder 1)))))
  1240. ;      (emit-move.l (make-disp* src (- type-PLACEHOLDER)) dst)
  1241. ;      (emit-cmp.l  src dst)
  1242. ;      (emit-bne    lbl1)
  1243.       (trap-to-touch-handler dst keep lbl1)))
  1244.  
  1245.   (if ofile-stats? (emit-stat '((touch 1 (non-placeholder 1)))))
  1246.  
  1247.   (cond ((dreg? src)
  1248.          (touch-dreg-to-reg src dst keep))
  1249.  
  1250.         ((dreg? dst)
  1251.          (touch-areg-to-dreg src dst keep))
  1252.  
  1253.         ((and keep (identical-opnd68? dtemp1 keep))
  1254.          (emit-exg src dtemp1)
  1255.          (touch-dreg-to-reg dtemp1 dst src)
  1256.          (emit-exg src dtemp1))
  1257.  
  1258.         (else
  1259.          (emit-move.l src dtemp1)
  1260.          (touch-dreg-to-reg dtemp1 dst keep))))
  1261.  
  1262. ; (touch-opnd-to-any-reg68 touch-opnd keep sn) generates the code to touch a
  1263. ; PVM 'potentially future' operand and put the result in any M68000 register.
  1264.  
  1265. (define (touch-opnd-to-any-reg68 touch-opnd keep sn)
  1266.   (let ((loc touch-opnd))
  1267.     (if (reg? loc)
  1268.  
  1269.       (let ((reg (reg->reg68 loc)))
  1270.         (touch-reg68-to-reg68 reg reg keep)
  1271.         reg)
  1272.  
  1273.       (let ((reg (if (and keep (identical-opnd68? keep dtemp1)) atemp1 dtemp1))
  1274.             (opnd (opnd->opnd68 loc keep sn)))
  1275.         (make-top-of-frame-if-stk-opnd68 opnd sn)
  1276.         (move-opnd                                            (frame-size frame)))))
  1277.                 (reg-list (map car order))
  1278.                 (nb-regs (length order)))
  1279.  
  1280.             (define (trap)
  1281.               (emit-trap2 num '())
  1282.               (gen-label-return* (new-lbl!)
  1283.                                  (add-first-class-label! source slots frame)
  1284.                                  slots
  1285.                                  0))
  1286.  
  1287.             (if save2
  1288.               (begin
  1289.                 (emit-move.l
  1290.                   (car save2)
  1291.                   (make-disp* sp-reg (* pointer-size (- current-fs ret-slot))))
  1292.                 (set-slot! slots ret-slot (cdr save2))))
  1293.  
  1294.             (if (> (length order) 2)
  1295.               (begin
  1296.                 (emit-movem.l reg-list pdec-sp)
  1297.                 (trap)
  1298.                 (emit-movem.l pinc-sp reg-list))
  1299.               (let loop2 ((l (reverse reg-list)))
  1300.                 (if (pair? l)
  1301.                   (let ((reg (car l)))
  1302.                     (emit-move.l reg pdec-sp)
  1303.                     (loop2 (cdr l))
  1304.                     (emit-move.l pinc-sp reg))
  1305.                   (trap))))
  1306.  
  1307.             (if save2
  1308.               (emit-move.l
  1309.                 (make-disp* sp-reg (* pointer-size (- current-fs ret-slot)))
  1310.                 (car save2)))
  1311.  
  1312.             (emit-label lbl)))))))
  1313.  
  1314. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1315.  
  1316. (define (gen-LABEL-SIMP lbl sn)
  1317.  
  1318.   (if ofile-stats?
  1319.     (begin
  1320.       (stat-clear!)
  1321.       (stat-add! '(pvm-instr label simp) 1)))
  1322.  
  1323.   (set! pointers-allocated 0)
  1324.  
  1325.   (emit-label lbl))
  1326.  
  1327. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1328.  
  1329. (define (gen-LABEL-PROC lbl nb-parms min rest? closed? sn)
  1330.  
  1331.   (if ofile-stats?
  1332.     (begin
  1333.       (stat-clear!)
  1334.       (stat-add! (list 'pvm-instr
  1335.                        'label
  1336.                        'proc
  1337.                        nb-parms
  1338.                        min
  1339.                        (if rest? 'rest 'not-rest)
  1340.                        (if closed? 'closed 'not-closed))
  1341.                  1)))
  1342.  
  1343.   (set! pointers-allocated 0)
  1344.  
  1345.   (let ((label-descr (add-first-class-label! instr-source '() exit-frame)))
  1346.     (if (= lbl entry-lbl-num)
  1347.       (emit-label lbl)
  1348.       (emit-label-subproc lbl entry-lbl-num label-descr)))
  1349.  
  1350.   (let* ((nb-parms* (if rest? (- nb-parms 1) nb-parms))
  1351.          (dispatch-lbls (make-vector (+ (- nb-parms min) 1)))
  1352.          (optional-lbls (make-vector (+ (- nb-parms min) 1))))
  1353.  
  1354.     (let loop ((i min))
  1355.       (if (<= i nb-parms)
  1356.         (let ((lbl (new-lbl!)))
  1357.           (vector-set! optional-lbls (- nb-parms i) lbl)
  1358.           (vector-set! dispatch-lbls (- nb-parms i)
  1359.             (if (or (>= i nb-parms) (<= nb-parms nb-arg-regs)) lbl (new-lbl!)))
  1360.           (loop (+ i 1)))))
  1361.  
  1362.     ; get closure pointer into the correct PVM register
  1363.  
  1364.     (if closed?
  1365.       (let ((closure-reg (reg-num->reg68 (+ nb-arg-regs 1))))
  1366.         (emit-move.l pinc-sp closure-reg)
  1367.         (emit-subq.l 6 closure-reg)
  1368.         (if (or (and (<= min 1) (<= 1 nb-parms*))
  1369.                 (and (<= min 2) (<= 2 nb-parms*)))
  1370.           (emit-move.w dtemp1 dtemp1))))
  1371.  
  1372.     ; dispatch on number of arguments passed
  1373.  
  1374.     (if (and (<= min 2) (<= 2 nb-parms*))
  1375.       (emit-beq (vector-ref dispatch-lbls (- nb-parms 2))))
  1376.  
  1377.     (if (and (<= min 1) (<= 1 nb-parms*))
  1378.       (emit-bmi (vector-ref dispatch-lbls (- nb-parms 1))))
  1379.  
  1380.     (let loop ((i min))
  1381.       (if (<= i nb-parms*)
  1382.         (begin
  1383.           (if (not (or (= i 1) (= i 2)))
  1384.             (begin
  1385.               (emit-cmp.w (make-imm (encode-arg-count i)) arg-count-reg)
  1386.               (emit-beq (vector-ref dispatch-lbls (- nb-parms i)))))
  1387.           (loop (+ i 1)))))
  1388.  
  1389.     ; trap to a handler if wrong number of args (or rest param not null)
  1390.  
  1391.     (cond (rest?
  1392.            (emit-trap1
  1393.              (if closed? rest-params-closed-trap rest-params-trap)
  1394.              (list min nb-parms*))
  1395.            (if (not closed?) (emit-lbl-ptr lbl))
  1396.            (set! pointers-allocated 1)
  1397.            (gen-guarantee-fudge)
  1398.            (emit-bra (vector-ref optional-lbls 0)))
  1399.           ((= min nb-parms*)
  1400.            (emit-trap1
  1401.              (if closed? wrong-nb-arg1-closed-trap wrong-nb-arg1-trap)
  1402.              (list nb-parms*))
  1403.            (if (not closed?) (emit-lbl-ptr lbl)))
  1404.           (else
  1405.            (emit-trap1
  1406.              (if closed? wrong-nb-arg2-closed-trap wrong-nb-arg2-trap)
  1407.              (list min nb-parms*))
  1408.            (if (not closed?) (emit-lbl-ptr lbl))))
  1409.  
  1410.     ; for each valid argument count with at least one optional, move
  1411.     ; arguments to correct parameter location (only needed if some of
  1412.     ; the parameters end up on the stack)
  1413.  
  1414.     (if (> nb-parms nb-arg-regs)
  1415.       (let loop1 ((i (- nb-parms 1)))
  1416.         (if (>= i min)
  1417.           (let ((nb-stacked (if (<= i nb-arg-regs) 0 (- i nb-arg-regs))))
  1418.             (emit-label (vector-ref dispatch-lbls (- nb-parms i)))
  1419.  
  1420.             (let loop2 ((j 1))
  1421.               (if (and (<= j nb-arg-regs)
  1422.                        (<= j i)
  1423.                        (<= j (- (- nb-parms nb-arg-regs) nb-stacked)))
  1424.                 (begin
  1425.                   (emit-move.l (reg-num->reg68 j) pdec-sp)
  1426.                   (loop2 (+ j 1)))
  1427.                 (let loop3 ((k j))
  1428.                   (if (and (<= k nb-arg-regs) (<= k i))
  1429.                     (begin
  1430.                       (emit-move.l (reg-num->reg68 k)
  1431.                                    (reg-num->reg68 (+ (- k j) 1)))
  1432.                       (loop3 (+ k 1)))))))
  1433.  
  1434.             (if (> i min)
  1435.               (emit-bra (vector-ref optional-lbls (- nb-parms i))))
  1436.             (loop1 (- i 1))))))
  1437.  
  1438.     ; for each valid argument count with at least one optional, set
  1439.     ; that parameter to an unassigned value (or the empty list for the
  1440.     ; rest parameter)
  1441.  
  1442.     (let loop ((i min))
  1443.       (if (<= i nb-parms)
  1444.         (let ((val (if (= i nb-parms*) bits-NULL bits-UNASS)))
  1445.           (emit-label (vector-ref optional-lbls (- nb-parms i)))
  1446.           (cond ((> (- nb-parms i) nb-arg-regs)
  1447.                  (move-n-to-loc68 val pdec-sp))
  1448.                 ((< i nb-parms)
  1449.                  (move-n-to-loc68
  1450.                    val
  1451.                    (reg-num->reg68 (parm->reg-num (+ i 1) nb-parms)))))
  1452.           (loop (+ i 1)))))))
  1453.  
  1454. (define (encode-arg-count n)
  1455.   (cond ((= n 1) -1)
  1456.         ((= n 2) 0)
  1457.         (else    (+ n 1))))
  1458.  
  1459. (define (parm->reg-num i nb-parms)
  1460.   (if (<= nb-parms nb-arg-regs) i (+ i (- nb-arg-regs nb-parms))))
  1461.  
  1462. (define (no-arg-check-entry-offset proc nb-args)
  1463.   (let ((x (proc-obj-call-pat proc)))
  1464.     (if (and (pair? x) (null? (cdr x))) ; proc accepts a fixed nb of args?
  1465.       (let ((arg-count (car x)))
  1466.         (if (= arg-count nb-args)
  1467.           (if (or (= arg-count 1) (= arg-count 2)) 10 14)
  1468.           0))
  1469.       0)))
  1470.  
  1471. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1472.  
  1473. (define (gen-LABEL-RETURN lbl method sn)
  1474.  
  1475.   (if ofile-stats?
  1476.     (begin
  1477.       (stat-clear!)
  1478.       (stat-add! (list 'pvm-instr 'label 'return method) 1)))
  1479.  
  1480.   (set! pointers-allocated 0)
  1481.  
  1482.   (let ((slots (frame-slots exit-frame)))
  1483.  
  1484.     (if (eq? method 'LAZY) ; return of a lazy future
  1485.  
  1486.       (case lazy-task-kind
  1487.  
  1488.         ((MESSAGE-PASSING-LTQ)
  1489.          (set! current-fs (+ current-fs 1))
  1490.          (let ((dummy-lbl (new-lbl!))
  1491.                (skip-lbl (new-lbl!)))
  1492.            (gen-label-return*
  1493.              dummy-lbl
  1494.              (add-first-class-label! instr-source slots exit-frame)
  1495.              slots
  1496.              1)
  1497.            (emit-bra skip-lbl)
  1498.            (gen-label-return-lazy*
  1499.              lbl
  1500.              (add-first-class-label! instr-source slots exit-frame)
  1501.              slots
  1502.              1)
  1503.            (emit-subq.l pointer-size ltq-tail-reg)
  1504.            (emit-label skip-lbl)))
  1505.  
  1506.         ((MESSAGE-PASSING-MIN)
  1507.          (let ((dummy-lbl (new-lbl!)))
  1508.            (gen-label-return*
  1509.              dummy-lbl
  1510.              (add-first-class-label! instr-source slots exit-frame)
  1511.              slots
  1512.              0)
  1513.            (emit-bra lbl)
  1514.            (gen-label-return-lazy*
  1515.              lbl
  1516.              (add-first-class-label! instr-source slots exit-frame)
  1517.              slots
  1518.              0)))
  1519.  
  1520.         ((SHARED-MEMORY)
  1521.          (set! current-fs (+ current-fs 1))
  1522.          (let ((conflict-lbl (new-lbl!))
  1523.                (dummy-lbl (new-lbl!))
  1524.                (skip-lbl (new-lbl!)))
  1525.            (emit-label conflict-lbl)
  1526.            (emit-trap1 steal-conflict-trap '())
  1527.            (gen-label-return*
  1528.              dummy-lbl
  1529.              (add-first-class-label! instr-source slots exit-frame)
  1530.              slots
  1531.              1)
  1532.            (emit-bra skip-lbl)
  1533.            (gen-label-return-lazy*
  1534.              lbl
  1535.              (add-first-class-label! instr-source slots exit-frame)
  1536.              slots
  1537.              1)
  1538.            (emit-clr.l (make-pdec ltq-tail-reg))
  1539.            (emit-cmp.l ltq-head-slot ltq-tail-reg)
  1540.            (emit-bcs   conflict-lbl)
  1541.            (emit-label skip-lbl)
  1542. ;           (emit-move.w false-reg (make-pdec ltq-tail-reg))
  1543. ;           (emit-move.w (make-pdec ltq-tail-reg) dtemp1)
  1544. ;           (emit-beq conflict-lbl)
  1545. ))
  1546.  
  1547.         (else
  1548.          (compiler-internal-error
  1549.            "gen-label-return, unknown 'lazy-task-kind':" lazy-task-kind)))
  1550.  
  1551.       (gen-label-return*
  1552.         lbl
  1553.         (add-first-class-label! instr-source slots exit-frame)
  1554.         slots
  1555.         0))))
  1556.  
  1557. (define (gen-label-return* lbl label-descr slots extra)
  1558.   (let ((i (pos-in-list ret-var slots)))
  1559.     (if i
  1560.       (let* ((fs (length slots))
  1561.              (link (- fs i)))
  1562.         (emit-label-return lbl entry-lbl-num (+ fs extra) link label-descr))
  1563.       (compiler-internal-error
  1564.         "gen-label-return*, no return address in frame"))))
  1565.  
  1566. (define (gen-label-return-lazy* lbl label-descr slots extra)
  1567.   (let ((i (pos-in-list ret-var slots)))
  1568.     (if i
  1569.       (let* ((fs (length slots))
  1570.              (link (- fs i)))
  1571.         (emit-label-return-lazy lbl entry-lbl-num (+ fs extra) link label-descr))
  1572.       (compiler-internal-error
  1573.         "gen-label-return-lazy*, no return address in frame"))))
  1574.  
  1575. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1576.  
  1577. (define (gen-LABEL-TASK lbl method sn)
  1578.  
  1579.   (define (build-delay ret-lbl)
  1580.     (gen-trap instr-source exit-frame #t #f delay-future-trap ret-lbl))
  1581.  
  1582.   (define (build-eager ret-lbl)
  1583.     (gen-trap instr-source exit-frame #t #f eager-future-trap ret-lbl))
  1584.  
  1585.   (define (build-lazy)
  1586.     (case lazy-task-kind
  1587.  
  1588.       ((MESSAGE-PASSING-LTQ SHARED-MEMORY)
  1589.        (if (= current-fs 0)
  1590.  
  1591.          (begin
  1592.            (emit-move.l (reg->reg68 return-reg) pdec-sp)
  1593.            (emit-move.l sp-reg (make-pinc ltq-tail-reg)))
  1594.  
  1595.          (begin
  1596.            (emit-move.l sp-reg atemp1)
  1597.            (emit-move.l (make-pinc atemp1) pdec-sp)
  1598.            (let loop ((i (- current-fs 1)))
  1599.              (if (> i 0)
  1600.                (begin
  1601.                  (emit-move.l (make-pinc atemp1) (make-disp atemp1 -8))
  1602.                  (loop (- i 1)))))
  1603.            (emit-move.l (reg->reg68 return-reg) (make-pdec atemp1))
  1604.            (emit-move.l atemp1 (make-pinc ltq-tail-reg)))))
  1605.  
  1606.       ((MESSAGE-PASSING-MIN)
  1607.        (emit-move.l false-reg ltq-tail-reg))
  1608.  
  1609.       (else
  1610.        (compiler-internal-error
  1611.          "gen-label-task, unknown 'lazy-task-kind':" lazy-task-kind))))
  1612.  
  1613.   (if ofile-stats?
  1614.     (begin
  1615.       (stat-clear!)
  1616.       (stat-add! (list 'pvm-instr 'label 'task method) 1)))
  1617.  
  1618.   (set! pointers-allocated 0)
  1619.  
  1620.   (emit-label lbl)
  1621.  
  1622.   (case method
  1623.     ((DELAY)
  1624.      (build-delay (new-lbl!)))
  1625.     ((EAGER)
  1626.      (build-eager (new-lbl!)))
  1627.     ((EAGER-INLINE)
  1628.      (let ((ret-lbl (new-lbl!)))
  1629.        (emit-cmp.l workq-head-slot null-reg)
  1630.        (emit-bne ret-lbl)
  1631.        (build-eager ret-lbl)))
  1632.     ((LAZY)
  1633.      (build-lazy))
  1634.     (else
  1635.      (compiler-internal-error
  1636.        "gen-LABEL-TASK, unknown task 'method':"
  1637.        method))))
  1638.  
  1639. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1640.  
  1641. (define (gen-APPLY prim opnds loc sn)
  1642.  
  1643.   (if ofile-stats?
  1644.     (begin
  1645.       (stat-add! (list 'pvm-instr
  1646.                        'apply
  1647.                        (string->canonical-symbol (proc-obj-name prim))
  1648.                        (map opnd-stat opnds)
  1649.                        (if loc (opnd-stat loc) #f))
  1650.                  1)
  1651.       (for-each fetch-stat-add! opnds)
  1652.       (if loc (store-stat-add! loc))))
  1653.  
  1654.   (let ((x (proc-obj-inlinable prim)))
  1655.     (if (not x)
  1656.       (compiler-internal-error "gen-APPLY, unknown 'prim':" prim)
  1657.       (if (or (needed? loc sn) (car x)) ; only inline primitive if result
  1658.         ((cdr x) opnds loc sn)))))      ; needed or prim. causes side effects?
  1659.  
  1660. (define (define-APPLY name side-effects? proc)
  1661.   (let ((prim (get-prim-info name)))
  1662.     (proc-obj-inlinable-set! prim (cons side-effects? proc))))
  1663.  
  1664. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1665.  
  1666. (define (gen-COPY opnd loc sn)
  1667.  
  1668.   (if ofile-stats?
  1669.     (begin
  1670.       (stat-add! (list 'pvm-instr 'copy (opnd-stat opnd) (opnd-stat loc)) 1)
  1671.       (fetch-stat-add! opnd)
  1672.       (store-stat-add! loc)))
  1673.  
  1674.   (if (needed? loc sn)
  1675.     (copy-opnd-to-loc opnd loc sn)))
  1676.  
  1677. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1678.  
  1679. (define (gen-MAKE_CLOSURES parms sn)
  1680.  
  1681.   (define (remove-touching-on-parms parms sn)
  1682.     (if (null? parms)
  1683.       '()
  1684.       (let* ((parm (car parms))
  1685.              (rest (remove-touching-on-parms (cdr parms) sn))
  1686.              (opnds (apply append (map (lambda (parm)
  1687.                                          (cons (closure-parms-loc parm)
  1688.                                                (closure-parms-opnds parm)))
  1689.                                        rest))))
  1690.         (cons (make-closure-parms
  1691.                 (remove-touching (closure-parms-loc parm)
  1692.                                  (sn-opnds opnds sn))
  1693.                 (closure-parms-lbl parm)
  1694.                 (closure-parms-opnds parm))
  1695.               rest))))
  1696.  
  1697.   (define (size->bytes size) ; must round to a cache line
  1698.     (* (quotient (+ (* (+ size 2) pointer-size)
  1699.                     (- cache-line-length 1))
  1700.                  cache-line-length)
  1701.        cache-line-length))
  1702.  
  1703.   (define (parms->bytes parms)
  1704.     (if (null? parms)
  1705.       0
  1706.       (+ (size->bytes (length (closure-parms-opnds (car parms))))
  1707.          (parms->bytes (cdr parms)))))
  1708.  
  1709.   (if ofile-stats?
  1710.     (begin
  1711.       (for-each (lambda (x)
  1712.                   (stat-add! (list 'pvm-instr
  1713.                                    'make_closure
  1714.                                    (opnd-stat (closure-parms-loc x))
  1715.                                    (map opnd-stat (closure-parms-opnds x)))
  1716.                              1)
  1717.                   (store-stat-add! (closure-parms-loc x))
  1718.                   (fetch-stat-add! (make-lbl (closure-parms-lbl x)))
  1719.                   (for-each fetch-stat-add! (closure-parms-opnds x)))
  1720.                 parms)))
  1721.  
  1722.   (let ((total-space-needed (parms->bytes parms))
  1723.         (lbl1 (new-lbl!)))
  1724.  
  1725.     (emit-move.l closure-ptr-slot atemp2)
  1726.     (move-n-to-loc68 total-space-needed dtemp1)
  1727.     (emit-sub.l dtemp1 atemp2)
  1728.     (emit-cmp.l closure-lim-slot atemp2)
  1729.     (emit-bcc   lbl1)
  1730.     (gen-trap instr-source entry-frame #f #f closure-alloc-trap lbl1)
  1731.     (emit-move.l atemp2 closure-ptr-slot)
  1732.  
  1733.     (let* ((parms* (remove-touching-on-parms parms sn))
  1734.            (opnds* (apply append (map closure-parms-opnds parms*)))
  1735.            (sn* (sn-opnds opnds* sn)))
  1736.  
  1737.       (let loop1 ((parms parms*))
  1738.         (let ((loc  (closure-parms-loc (car parms)))
  1739.               (size (length (closure-parms-opnds (car parms))))
  1740.               (rest (cdr parms)))
  1741.           (if (= size 1)
  1742.             (emit-addq.l type-PROCEDURE atemp2)
  1743.             (emit-move.w (make-imm (+ #x8000 (* (+ size 1) 4)))
  1744.                          (make-pinc atemp2)))
  1745.           (move-opnd68-to-loc atemp2 loc (sn-opnds (map closure-parms-loc rest) sn*))
  1746.           (if (null? rest)
  1747.             (add-n-to-loc68 (+ (- (size->bytes size) total-space-needed) 2) atemp2)
  1748.             (begin
  1749.               (add-n-to-loc68 (- (size->bytes size) type-PROCEDURE) atemp2)
  1750.               (loop1 rest)))))
  1751.  
  1752.       (let loop2 ((parms parms*))
  1753.         (let* ((opnds (closure-parms-opnds (car parms)))
  1754.                (lbl   (closure-parms-lbl (car parms)))
  1755.                (size  (length opnds))
  1756.                (rest  (cdr parms)))
  1757.  
  1758.           (emit-lea (make-pcr lbl 0) atemp1)
  1759.           (emit-move.l atemp1 (make-pinc atemp2))
  1760.  
  1761.           (let loop3 ((opnds opnds))
  1762.             (if (not (null? opnds))
  1763.               (let ((sn** (sn-opnds (apply append (map closure-parms-opnds rest)) sn)))
  1764.                 (move-opnd-to-loc68 (car opnds)
  1765.                                     (make-pinc atemp2)
  1766.                                     (sn-opnds (cdr opnds) sn**))
  1767.                 (loop3 (cdr opnds)))))
  1768.  
  1769.           (if (not (null? rest))
  1770.             (begin
  1771.               (add-n-to-loc68 (- (size->bytes size) (* (+ size 1) pointer-size)) atemp2)
  1772.               (loop2 rest))))))))
  1773.  
  1774. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1775.  
  1776. (define (gen-COND test opnds true-lbl false-lbl intr-check? next-lbl)
  1777.  
  1778.   (if ofile-stats?
  1779.     (begin
  1780.       (stat-add! (list 'pvm-instr
  1781.                        'cond
  1782.                        (string->canonical-symbol (proc-obj-name test))
  1783.                        (map opnd-stat opnds)
  1784.                        (if intr-check? 'intr-check 'not-intr-check))
  1785.                  1)
  1786.       (for-each fetch-stat-add! opnds)
  1787.       (stat-dump!)))
  1788.  
  1789.   (let ((proc (proc-obj-test test)))
  1790.     (if proc
  1791.       (gen-COND* proc opnds true-lbl false-lbl intr-check? next-lbl)
  1792.       (compiler-internal-error "gen-COND, unknown 'test':" test))))
  1793.  
  1794. (define (gen-COND* proc opnds true-lbl false-lbl intr-check? next-lbl)
  1795.   (let ((fs (frame-size exit-frame)))
  1796.  
  1797.     (define (double-branch)
  1798.       (proc #t opnds false-lbl fs)
  1799.       (if ofile-stats?
  1800.         (emit-stat '((pvm-instr.cond.fall-through 1)
  1801.                      (pvm-instr.cond.double-branch 1))))
  1802.       (emit-bra true-lbl)
  1803.       (gen-deferred-code!))
  1804.  
  1805.     (gen-guarantee-fudge)
  1806.  
  1807.     (if intr-check?
  1808.       (gen-intr-check))
  1809.  
  1810.     (if next-lbl
  1811.       (cond ((= true-lbl next-lbl)
  1812.              (proc #t opnds false-lbl fs)
  1813.              (if ofile-stats?
  1814.                (emit-stat '((pvm-instr.cond.fall-through 1)))))
  1815.             ((= false-lbl next-lbl)
  1816.              (proc #f opnds true-lbl fs)
  1817.              (if ofile-stats?
  1818.                (emit-stat '((pvm-instr.cond.fall-through 1)))))
  1819.             (else
  1820.              (double-branch)))
  1821.       (double-branch))))
  1822.  
  1823. (define (define-COND name proc)
  1824.  
  1825.   (define-APPLY name #f (lambda (opnds loc sn)
  1826.     (let ((true-lbl (new-lbl!))
  1827.           (cont-lbl (new-lbl!))
  1828.           (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  1829.                    (reg->reg68 loc)
  1830.                    dtemp1)))
  1831.  
  1832.       (proc #f opnds true-lbl current-fs)
  1833.       (move-n-to-loc68 bits-FALSE reg68)
  1834.       (emit-bra cont-lbl)
  1835.       (emit-label true-lbl)
  1836.       (move-n-to-loc68 bits-TRUE reg68)
  1837.       (emit-label cont-lbl)
  1838.  
  1839.       (move-opnd68-to-loc reg68 loc sn))))
  1840.  
  1841.   (proc-obj-test-set! (get-prim-info name) proc))
  1842.  
  1843. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1844.  
  1845. (define (gen-JUMP opnd nb-args intr-check? next-lbl)
  1846.   (let ((fs (frame-size exit-frame)))
  1847.  
  1848.     (if ofile-stats?
  1849.       (begin
  1850.         (stat-add! (list 'pvm-instr
  1851.                          'jump
  1852.                          (opnd-stat opnd)
  1853.                          nb-args
  1854.                          (if intr-check? 'intr-check 'not-intr-check))
  1855.                    1)
  1856.         (jump-stat-add! opnd)
  1857.         (if (and (lbl? opnd) next-lbl (= next-lbl (lbl-num opnd)))
  1858.           (stat-add! '(pvm-instr.jump.fall-through) 1))
  1859.         (stat-dump!)))
  1860.  
  1861.     (gen-guarantee-fudge)
  1862.     (cond ((glo? opnd)
  1863.            (if intr-check? (gen-intr-check))
  1864.            (setup-jump fs nb-args)
  1865.            (emit-jmp-glob (make-glob (glo-name opnd)))
  1866.            (gen-deferred-code!))
  1867.           ((and (stk? opnd) (= (stk-num opnd) (+ fs 1)) (not nb-args))
  1868.            (if intr-check? (gen-intr-check))
  1869.            (setup-jump (+ fs 1) nb-args)
  1870.            (emit-rts)
  1871.            (gen-deferred-code!))
  1872.           ((lbl? opnd)
  1873.            (if (and intr-check?
  1874.                     (= fs current-fs)
  1875.                     (not nb-args)
  1876.                     (not (and next-lbl (= next-lbl (lbl-num opnd)))))
  1877.              (gen-intr-check-branch (lbl-num opnd))
  1878.              (begin
  1879.                (if intr-check? (gen-intr-check))
  1880.                (setup-jump fs nb-args)
  1881.                (if (not (and next-lbl (= next-lbl (lbl-num opnd))))
  1882.                  (emit-bra (lbl-num opnd))))))
  1883.           ((obj? opnd)
  1884.            (if intr-check? (gen-intr-check))
  1885.            (let ((val (obj-val opnd)))
  1886.              (if (proc-obj? val)
  1887.                (let ((num (add-object val))
  1888.                      (offset (no-arg-check-entry-offset val nb-args)))
  1889.                  (setup-jump fs (if (<= offset 0) nb-args #f))
  1890.                  (if num
  1891.                    (emit-jmp-proc num offset)
  1892.                    (emit-jmp-prim val offset))
  1893.                  (gen-deferred-code!))
  1894.                (gen-JUMP* (opnd->opnd68 opnd #f fs) fs nb-args))))
  1895.           (else
  1896.            (if intr-check? (gen-intr-check))
  1897.            (gen-JUMP* (opnd->opnd68 opnd #f fs) fs nb-args)))))
  1898.  
  1899. (define (gen-JUMP* opnd fs nb-args)
  1900.   (if nb-args
  1901.     (let ((lbl (new-lbl!)))
  1902.       (make-top-of-frame-if-stk-opnd68 opnd fs)
  1903.       (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd fs) atemp1)
  1904.       (shrink-frame fs)
  1905.       (emit-move.l atemp1 dtemp1)
  1906.       (emit-addq.w (modulo (- type-PAIR type-PROCEDURE) 8) dtemp1)
  1907.       (emit-btst   dtemp1 pair-reg)
  1908.       (emit-beq    lbl)
  1909.       (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg)
  1910.       (emit-trap3 non-proc-jump-trap)
  1911.       (emit-label lbl)
  1912.       (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg)
  1913.       (emit-jmp (make-ind atemp1)))
  1914.     (let ((areg (move-opnd68-to-any-areg opnd #f fs)))
  1915.       (setup-jump fs nb-args)
  1916.       (emit-jmp (make-ind areg))))
  1917.   (gen-deferred-code!))
  1918.  
  1919. (define (setup-jump fs nb-args)
  1920.   (shrink-frame fs)
  1921.   (if nb-args
  1922.     (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg)))
  1923.  
  1924. (define (gen-intr-check)
  1925.   (let ((lbl (new-lbl!)))
  1926.     (emit-dbra  intr-timer-reg lbl)
  1927.     (if (not (eq? lazy-task-kind 'SHARED-MEMORY))
  1928.       (emit-move.l ltq-tail-reg ltq-tail-slot))
  1929.     (emit-moveq (- intr-latency 1) intr-timer-reg)
  1930.     (emit-cmp.l intr-flag-slot sp-reg)
  1931.     (emit-bcc   lbl)
  1932.     (gen-trap instr-source entry-frame #f #f intr-trap lbl)))
  1933.  
  1934. (define (gen-intr-check-branch lbl)
  1935.   (emit-dbra  intr-timer-reg lbl)
  1936.   (if (not (eq? lazy-task-kind 'SHARED-MEMORY))
  1937.     (emit-move.l ltq-tail-reg ltq-tail-slot))
  1938.   (emit-moveq (- intr-latency 1) intr-timer-reg)
  1939.   (emit-cmp.l intr-flag-slot sp-reg)
  1940.   (emit-bcc   lbl)
  1941.   (gen-trap instr-source entry-frame #f #f intr-trap (new-lbl!))
  1942.   (emit-bra   lbl))
  1943.  
  1944. ;------------------------------------------------------------------------------
  1945.  
  1946. ; Definitions used for APPLY and COND instructions:
  1947.  
  1948. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1949.  
  1950. ; for inlining reference and assignment to slot of an object
  1951.  
  1952. (define (make-gen-slot-ref slot type)
  1953.   (lambda (opnds loc sn)
  1954.     (let* ((sn-loc (sn-opnd loc sn))
  1955.            (opnd (touch-operand (car opnds) sn-loc)))
  1956.       (move-opnd-to-loc68 opnd atemp1 sn-loc)
  1957.       (move-opnd68-to-loc (make-disp* atemp1 (- (* slot pointer-size) type))
  1958.                           loc
  1959.                           sn))))
  1960.  
  1961. (define (make-gen-slot-set! slot type)
  1962.   (lambda (opnds loc sn)
  1963.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  1964.            (opnds (touch-operands opnds '(1) sn-loc)))
  1965.       (let* ((first-opnd (car opnds))
  1966.              (second-opnd (cadr opnds))
  1967.              (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  1968.         (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd)
  1969.         (move-opnd-to-loc68 second-opnd
  1970.                             (make-disp* atemp1 (- (* slot pointer-size) type))
  1971.                             sn-loc)
  1972.         (if loc
  1973.           (if (not (eq? first-opnd loc))
  1974.             (move-opnd68-to-loc atemp1 loc sn)))))))
  1975.  
  1976. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1977.  
  1978. ; for inlining CONS
  1979.  
  1980. (define (gen-cons weak? opnds loc sn)
  1981.   (let* ((sn-loc (sn-opnd loc sn))
  1982.          (opnds (touch-operands opnds '() sn-loc)))
  1983.     (let ((first-opnd (car opnds))
  1984.           (second-opnd (cadr opnds)))
  1985.  
  1986.       (gen-guarantee-space 2)
  1987.  
  1988.       (if (or (contains-opnd? loc second-opnd) (might-touch-opnd? loc) weak?)
  1989.  
  1990.         (let ((sn-second-opnd (sn-opnd second-opnd sn-loc)))
  1991.           (move-opnd-to-loc68 first-opnd (make-pdec heap-reg) sn-second-opnd)
  1992.           (move-opnd68-to-loc68 heap-reg atemp2) ; *** atemp2 should be safe
  1993.           (move-opnd-to-loc68 second-opnd (make-pdec heap-reg) sn-loc)
  1994.           (if weak? (emit-subq.l (modulo (- type-PAIR type-WEAK-PAIR) 8) atemp2))
  1995.           (move-opnd68-to-loc atemp2 loc sn))
  1996.  
  1997.         (let* ((sn-second-opnd (sn-opnd second-opnd sn))
  1998.                (sn-loc (sn-opnd loc sn-second-opnd)))
  1999.           (move-opnd-to-loc68 first-opnd (make-pdec heap-reg) sn-loc)
  2000.           (move-opnd68-to-loc heap-reg loc sn-second-opnd)
  2001.           (move-opnd-to-loc68 second-opnd (make-pdec heap-reg) sn))))))
  2002.  
  2003. ; for inlining of CAR/CDR chains
  2004.  
  2005. (define (make-gen-APPLY-C...R weak? pattern)
  2006.   (lambda (opnds loc sn)
  2007.     (let* ((sn-loc (sn-opnd loc sn))
  2008.            (opnd (touch-operand (car opnds) sn-loc)))
  2009.  
  2010.       (move-opnd-to-loc68 opnd atemp1 sn-loc)
  2011.  
  2012.       (let loop ((pattern pattern))
  2013.         (if (<= pattern 3)
  2014.           (if (= pattern 3)
  2015.             (if weak?
  2016.               (move-opnd68-to-loc (make-disp* atemp1 (- type-WEAK-PAIR)) loc sn)
  2017.               (move-opnd68-to-loc (make-pdec atemp1) loc sn)) ; cdr
  2018.             (if weak?
  2019.               (move-opnd68-to-loc (make-disp* atemp1 (- type-PAIR type-WEAK-PAIR)) loc sn)
  2020.               (move-opnd68-to-loc (make-ind atemp1) loc sn))) ; car
  2021.           (begin
  2022.             (if (odd? pattern)
  2023.               (if weak?
  2024.                 (emit-move.l (make-disp* atemp1 (- type-WEAK-PAIR)) atemp1)
  2025.                 (emit-move.l (make-pdec atemp1) atemp1)) ; cdr
  2026.               (if weak?
  2027.                 (emit-move.l (make-disp* atemp1 (- type-PAIR type-WEAK-PAIR)) atemp1)
  2028.                 (emit-move.l (make-ind atemp1) atemp1))) ; car
  2029.             (if touch-C...R?
  2030.               (touch-reg68-to-reg68 atemp1 atemp1 #f))
  2031.             (loop (quotient pattern 2))))))))
  2032.  
  2033. (define touch-C...R? #t)
  2034.  
  2035. ; for inlining assignments to CAR/CDR
  2036.  
  2037. (define (gen-set-car! weak? opnds loc sn)
  2038.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2039.          (opnds (touch-operands opnds '(1) sn-loc)))
  2040.     (let* ((first-opnd (car opnds))
  2041.            (second-opnd (cadr opnds))
  2042.            (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2043.       (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd)
  2044.       (if weak?
  2045.         (move-opnd-to-loc68 second-opnd (make-disp* atemp1 (- type-PAIR type-WEAK-PAIR)) sn-loc)
  2046.         (move-opnd-to-loc68 second-opnd (make-ind atemp1) sn-loc))
  2047.       (if (and loc (not (eq? first-opnd loc)))
  2048.         (move-opnd68-to-loc atemp1 loc sn)))))
  2049.  
  2050. (define (gen-set-cdr! weak? opnds loc sn)
  2051.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2052.          (opnds (touch-operands opnds '(1) sn-loc)))
  2053.     (let* ((first-opnd (car opnds))
  2054.            (second-opnd (cadr opnds))
  2055.            (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2056.       (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd)
  2057.       (if weak?
  2058.         (move-opnd-to-loc68 second-opnd (make-disp* atemp1 (- type-WEAK-PAIR)) sn-loc)
  2059.         (if (and loc (not (eq? first-opnd loc)))
  2060.           (move-opnd-to-loc68 second-opnd (make-disp atemp1 (- pointer-size)) sn-loc)
  2061.           (move-opnd-to-loc68 second-opnd (make-pdec atemp1) sn-loc)))
  2062.       (if (and loc (not (eq? first-opnd loc)))
  2063.         (move-opnd68-to-loc atemp1 loc sn)))))
  2064.  
  2065. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2066.  
  2067. ; for inlining of fixnum arithmetic
  2068.  
  2069. (define (commut-oper gen opnds loc sn self? accum-self accum-other)
  2070.   (if (null? opnds)
  2071.     (gen (reverse accum-self) (reverse accum-other) loc sn self?)
  2072.     (let ((opnd (car opnds))
  2073.           (rest (cdr opnds)))
  2074.       (cond ((and (not self?) (eq? opnd loc))
  2075.              (commut-oper gen rest loc sn #t accum-self accum-other))
  2076.             ((contains-opnd? loc opnd)
  2077.              (commut-oper gen rest loc sn self? (cons opnd accum-self) accum-other))
  2078.             (else
  2079.              (commut-oper gen rest loc sn self? accum-self (cons opnd accum-other)))))))
  2080.  
  2081. (define (gen-add-in-place opnds loc68 sn)
  2082.   (if (not (null? opnds))
  2083.     (let* ((first-opnd (car opnds))
  2084.            (other-opnds (cdr opnds))
  2085.            (sn-other-opnds (sn-opnds other-opnds sn))
  2086.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2087.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 loc68) (sn-opnd68 loc68 sn))))
  2088.       (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds)
  2089.       (if (imm? opnd68)
  2090.         (add-n-to-loc68 (imm-val opnd68) (opnd68->true-opnd68 loc68 sn-other-opnds))
  2091.         (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2092.           (if (or (dreg? opnd68) (reg68? loc68))
  2093.             (emit-add.l opnd68* (opnd68->true-opnd68 loc68 sn-other-opnds))
  2094.             (begin
  2095.               (move-opnd68-to-loc68 opnd68* dtemp1)
  2096.               (emit-add.l dtemp1 (opnd68->true-opnd68 loc68 sn-other-opnds))))))
  2097.       (gen-add-in-place other-opnds loc68 sn))))
  2098.  
  2099. (define (gen-add self-opnds other-opnds loc sn self?)
  2100.   (let* ((opnds (append self-opnds other-opnds))
  2101.          (first-opnd (car opnds))
  2102.          (other-opnds (cdr opnds))
  2103.          (sn-other-opnds (sn-opnds other-opnds sn))
  2104.          (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2105.     (if (<= (length self-opnds) 1) ; loc must be reg or stk
  2106.  
  2107.       (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2108.         (if self?
  2109.           (gen-add-in-place opnds loc68 sn)
  2110.           (begin
  2111.             (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)
  2112.             (gen-add-in-place other-opnds loc68 sn))))
  2113.  
  2114.       (begin
  2115.         (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2116.         (gen-add-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2117.         (if self?
  2118.           (let ((loc68 (loc->loc68 loc dtemp1 sn)))
  2119.             (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2120.             (emit-add.l dtemp1 (opnd68->true-opnd68 loc68 sn)))
  2121.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2122.  
  2123. (define (gen-sub-in-place opnds loc68 sn)
  2124.   (if (not (null? opnds))
  2125.     (let* ((first-opnd (car opnds))
  2126.            (other-opnds (cdr opnds))
  2127.            (sn-other-opnds (sn-opnds other-opnds sn))
  2128.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2129.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 loc68) (sn-opnd68 loc68 sn))))
  2130.       (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds)
  2131.       (if (imm? opnd68)
  2132.         (add-n-to-loc68 (- (imm-val opnd68)) (opnd68->true-opnd68 loc68 sn-other-opnds))
  2133.         (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2134.           (if (or (dreg? opnd68) (reg68? loc68))
  2135.             (emit-sub.l opnd68* (opnd68->true-opnd68 loc68 sn-other-opnds))
  2136.             (begin
  2137.               (move-opnd68-to-loc68 opnd68* dtemp1)
  2138.               (emit-sub.l dtemp1 (opnd68->true-opnd68 loc68 sn-other-opnds))))))
  2139.       (gen-sub-in-place other-opnds loc68 sn))))
  2140.  
  2141. (define (gen-sub first-opnd other-opnds loc sn self-opnds?)
  2142.   (if (null? other-opnds) ; we are negating a location
  2143.  
  2144.     (if (and (or (reg? loc) (stk? loc))
  2145.              (not (eq? loc return-reg)))
  2146.  
  2147.       (begin
  2148.         (copy-opnd-to-loc first-opnd loc (sn-opnd loc sn))
  2149.         (let ((loc68 (loc->loc68 loc #f sn)))
  2150.           (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2151.           (emit-neg.l (opnd68->true-opnd68 loc68 sn))))
  2152.  
  2153.       (begin
  2154.         (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn))
  2155.         (emit-neg.l dtemp1)
  2156.         (move-opnd68-to-loc dtemp1 loc sn)))
  2157.  
  2158.     (let* ((sn-other-opnds (sn-opnds other-opnds sn))
  2159.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2160.  
  2161.       (if (and (not self-opnds?)
  2162.                (or (reg? loc) (stk? loc)))
  2163.  
  2164.         (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2165.           (if (not (eq? first-opnd loc))
  2166.             (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds))
  2167.           (gen-sub-in-place other-opnds loc68 sn))
  2168.  
  2169.         (begin
  2170.           (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2171.           (gen-sub-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2172.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2173.  
  2174. (define (gen-mul-in-place opnds reg68 sn)
  2175.   (if (not (null? opnds))
  2176.     (let* ((first-opnd (car opnds))
  2177.            (other-opnds (cdr opnds))
  2178.            (sn-other-opnds (sn-opnds other-opnds sn))
  2179.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 reg68) sn)))
  2180.       (make-top-of-frame-if-stk-opnd68 opnd68 sn-other-opnds)
  2181.       (if (imm? opnd68)
  2182.         (mul-n-to-reg68 (quotient (imm-val opnd68) 8) reg68)
  2183.         (begin
  2184.           (emit-asr.l (make-imm 3) reg68)
  2185.           (emit-muls.l (opnd68->true-opnd68 opnd68 sn-other-opnds) reg68)))
  2186.       (gen-mul-in-place other-opnds reg68 sn))))
  2187.  
  2188. (define (gen-mul self-opnds other-opnds loc sn self?)
  2189.   (let* ((opnds (append self-opnds other-opnds))
  2190.          (first-opnd (car opnds))
  2191.          (other-opnds (cdr opnds))
  2192.          (sn-other-opnds (sn-opnds other-opnds sn))
  2193.          (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2194.     (if (null? self-opnds) ; loc must be reg
  2195.  
  2196.       (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2197.         (if self?
  2198.           (gen-mul-in-place opnds loc68 sn)
  2199.           (begin
  2200.             (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)
  2201.             (gen-mul-in-place other-opnds loc68 sn))))
  2202.  
  2203.       (begin
  2204.         (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2205.         (gen-mul-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2206.         (if self?
  2207.           (let ((loc68 (loc->loc68 loc dtemp1 sn)))
  2208.             (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2209.             (emit-asr.l (make-imm 3) dtemp1)
  2210.             (emit-muls.l dtemp1 (opnd68->true-opnd68 loc68 sn)))
  2211.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2212.  
  2213. (define (gen-div-in-place opnds reg68 sn)
  2214.   (if (not (null? opnds))
  2215.     (let* ((first-opnd (car opnds))
  2216.            (other-opnds (cdr opnds))
  2217.            (sn-other-opnds (sn-opnds other-opnds sn))
  2218.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2219.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 reg68) sn)))
  2220.       (make-top-of-frame-if-stk-opnd68 opnd68 sn-other-opnds)
  2221.       (if (imm? opnd68)
  2222.         (let ((n (quotient (imm-val opnd68) 8)))
  2223.           (div-n-to-reg68 n reg68)
  2224.           (if (> (abs n) 1)
  2225.             (emit-and.w (make-imm -8) reg68)))
  2226.         (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2227.           (emit-divsl.l opnd68* reg68 reg68)
  2228.           (emit-asl.l (make-imm 3) reg68)))
  2229.       (gen-div-in-place other-opnds reg68 sn))))
  2230.  
  2231. (define (gen-div first-opnd other-opnds loc sn self-opnds?)
  2232.   (if (null? other-opnds) ; we are inverting a location
  2233.  
  2234.     (begin
  2235.       (move-opnd-to-loc68 first-opnd pdec-sp (sn-opnd loc sn))
  2236.       (emit-moveq 8 dtemp1)
  2237.       (emit-divsl.l pinc-sp dtemp1 dtemp1)
  2238.       (emit-asl.l (make-imm 3) dtemp1)
  2239.       (emit-and.w (make-imm -8) dtemp1)
  2240.       (move-opnd68-to-loc dtemp1 loc sn))
  2241.  
  2242.     (let* ((sn-other-opnds (sn-opnds other-opnds sn))
  2243.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2244.  
  2245.       (if (and (reg? loc)
  2246.                (not self-opnds?)
  2247.                (not (eq? loc return-reg)))
  2248.  
  2249.         (let ((reg68 (reg->reg68 loc)))
  2250.           (if (not (eq? first-opnd loc))
  2251.             (move-opnd-to-loc68 first-opnd reg68 sn-other-opnds))
  2252.           (gen-div-in-place other-opnds reg68 sn))
  2253.  
  2254.         (begin
  2255.           (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2256.           (gen-div-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2257.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2258.  
  2259. (define (gen-rem first-opnd second-opnd loc sn)
  2260.   (let* ((sn-loc (sn-opnd loc sn))
  2261.          (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2262.     (move-opnd-to-loc68 first-opnd dtemp1 sn-second-opnd)
  2263.     (let ((opnd68 (opnd->opnd68 second-opnd #f sn-loc))
  2264.           (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2265.                    (reg->reg68 loc)
  2266.                    false-reg)))
  2267.       (make-top-of-frame-if-stk-opnd68 opnd68 sn-loc)
  2268.       (let ((opnd68* (if (areg? opnd68)
  2269.                        (begin (emit-move.l opnd68 reg68) reg68)
  2270.                        (opnd68->true-opnd68 opnd68 sn-loc))))
  2271.         (emit-divsl.l opnd68* reg68 dtemp1))
  2272.       (move-opnd68-to-loc reg68 loc sn)
  2273.       (if (not (and (reg? loc) (not (eq? loc return-reg))))
  2274.         (emit-move.l (make-imm bits-FALSE) false-reg)))))
  2275.  
  2276. (define (gen-mod first-opnd second-opnd loc sn)
  2277.   (let* ((sn-loc (sn-opnd loc sn))
  2278.          (sn-first-opnd (sn-opnd first-opnd sn-loc))
  2279.          (sn-second-opnd (sn-opnd second-opnd sn-first-opnd))
  2280.          (opnd68 (opnd->opnd68 second-opnd #f sn-second-opnd)))
  2281.  
  2282.     (define (general-case)
  2283.       (let ((lbl1 (new-lbl!))
  2284.             (lbl2 (new-lbl!))
  2285.             (lbl3 (new-lbl!))
  2286.             (opnd68** (opnd68->true-opnd68 opnd68 sn-second-opnd))
  2287.             (opnd68* (opnd68->true-opnd68
  2288.                        (opnd->opnd68 first-opnd #f sn-second-opnd)
  2289.                        sn-second-opnd)))
  2290.         (move-opnd68-to-loc68 opnd68* dtemp1)
  2291.         (move-opnd68-to-loc68 opnd68** false-reg)
  2292.         (emit-divsl.l false-reg false-reg dtemp1) ; false-reg <-- remainder
  2293.         (emit-move.l false-reg false-reg)
  2294.         (emit-beq lbl3) ; done if remainder = 0
  2295.         (move-opnd68-to-loc68 opnd68* dtemp1)
  2296.         (emit-bmi lbl1)
  2297.         (move-opnd68-to-loc68 opnd68** dtemp1)
  2298.         (emit-bpl lbl3)
  2299.         (emit-bra lbl2)
  2300.         (emit-label lbl1)
  2301.         (move-opnd68-to-loc68 opnd68** dtemp1)
  2302.         (emit-bmi lbl3)
  2303.         (emit-label lbl2) ; first and second operand have different signs
  2304.         (emit-add.l dtemp1 false-reg)
  2305.         (emit-label lbl3)
  2306.         (move-opnd68-to-loc false-reg loc sn)
  2307.         (emit-move.l (make-imm bits-FALSE) false-reg)))
  2308.  
  2309.     (make-top-of-frame-if-stk-opnd68 opnd68 sn-first-opnd)
  2310.     (if (imm? opnd68)
  2311.       (let ((n (quotient (imm-val opnd68) 8)))
  2312.         (if (> n 0)
  2313.           (let ((shift (power-of-2 n)))
  2314.             (if shift
  2315.               (let ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2316.                              (reg->reg68 loc)
  2317.                              dtemp1)))
  2318.                 (move-opnd-to-loc68 first-opnd reg68 sn-loc)
  2319.                 (emit-and.l (make-imm (* (- n 1) 8)) reg68)
  2320.                 (move-opnd68-to-loc reg68 loc sn))
  2321.               (general-case)))
  2322.           (general-case)))
  2323.       (general-case))))
  2324.  
  2325. (define (gen-op emit-op dst-ok?)
  2326.  
  2327.   (define (gen-op-in-place opnds loc68 sn)
  2328.     (if (not (null? opnds))
  2329.       (let* ((first-opnd (car opnds))
  2330.              (other-opnds (cdr opnds))
  2331.              (sn-other-opnds (sn-opnds other-opnds sn))
  2332.              (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2333.              (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 loc68) (sn-opnd68 loc68 sn))))
  2334.         (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds)
  2335.         (if (imm? opnd68)
  2336.           (emit-op opnd68 (opnd68->true-opnd68 loc68 sn-other-opnds))
  2337.           (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2338.             (if (or (dreg? opnd68) (dst-ok? loc68))
  2339.               (emit-op opnd68* (opnd68->true-opnd68 loc68 sn-other-opnds))
  2340.               (begin
  2341.                 (move-opnd68-to-loc68 opnd68* dtemp1)
  2342.                 (emit-op dtemp1 (opnd68->true-opnd68 loc68 sn-other-opnds))))))
  2343.         (gen-op-in-place other-opnds loc68 sn))))
  2344.  
  2345.   (lambda (self-opnds other-opnds loc sn self?)
  2346.     (let* ((opnds (append self-opnds other-opnds))
  2347.            (first-opnd (car opnds))
  2348.            (other-opnds (cdr opnds))
  2349.            (sn-other-opnds (sn-opnds other-opnds sn))
  2350.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2351.       (if (<= (length self-opnds) 1) ; loc must be reg or stk
  2352.  
  2353.         (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2354.           (if self?
  2355.             (gen-op-in-place opnds loc68 sn)
  2356.             (begin
  2357.               (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)
  2358.               (gen-op-in-place other-opnds loc68 sn))))
  2359.  
  2360.         (begin
  2361.           (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2362.           (gen-op-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2363.           (if self?
  2364.             (let ((loc68 (loc->loc68 loc dtemp1 sn)))
  2365.               (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2366.               (emit-op dtemp1 (opnd68->true-opnd68 loc68 sn)))
  2367.             (move-opnd68-to-loc dtemp1 loc sn)))))))
  2368.  
  2369. (define gen-logior (gen-op emit-or.l dreg?))
  2370. (define gen-logxor (gen-op emit-eor.l (lambda (x) #f)))
  2371. (define gen-logand (gen-op emit-and.l dreg?))
  2372.  
  2373. (define (gen-shift right-shift)
  2374.  
  2375.   (lambda (opnds loc sn)
  2376.     (let* ((sn-loc (sn-opnd loc sn))
  2377.            (opnds (touch-operands opnds '0 sn-loc)))
  2378.       (let* ((opnd1 (car opnds))
  2379.              (opnd2 (cadr opnds))
  2380.              (sn-opnd1 (sn-opnd opnd1 sn-loc))
  2381.              (o2 (opnd->opnd68 opnd2 #f sn-opnd1)))
  2382.         (make-top-of-frame-if-stk-opnd68 o2 sn-opnd1)
  2383.         (if (imm? o2)
  2384.  
  2385.           (let* ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2386.                           (reg->reg68 loc)
  2387.                           dtemp1))
  2388.                  (n (quotient (imm-val o2) 8))
  2389.                 (emit-shft (if (> n 0) emit-lsl.l right-shift)))
  2390.             (move-opnd-to-loc68 opnd1 reg68 sn-loc)
  2391.             (let loop ((i (min (abs n) 29)))
  2392.               (if (> i 0)
  2393.                 (begin (emit-shft (make-imm (min i 8)) reg68) (loop (- i 8)))))
  2394.             (if (< n 0)
  2395.               (emit-and.w (make-imm -8) reg68))
  2396.             (move-opnd68-to-loc reg68 loc sn))
  2397.  
  2398.           (let* ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2399.                           (reg->reg68 loc)
  2400.                           dtemp1))
  2401.                  (reg68* (if (and (reg? loc) (not (eq? loc return-reg)))
  2402.                            dtemp1
  2403.                            false-reg))
  2404.                  (lbl1 (new-lbl!))
  2405.                  (lbl2 (new-lbl!)))
  2406.             (emit-move.l (opnd68->true-opnd68 o2 sn-opnd1) reg68*)
  2407.             (move-opnd-to-loc68 opnd1 reg68 sn-loc)
  2408.             (emit-asr.l (make-imm 3) reg68*)
  2409.             (emit-bmi lbl1)
  2410.             (emit-lsl.l reg68* reg68)
  2411.             (emit-bra lbl2)
  2412.             (emit-label lbl1)
  2413.             (emit-neg.l reg68*)
  2414.             (right-shift reg68* reg68)
  2415.             (emit-and.w (make-imm -8) reg68)
  2416.             (emit-label lbl2)
  2417.             (move-opnd68-to-loc reg68 loc sn)
  2418.             (if (not (and (reg? loc) (not (eq? loc return-reg))))
  2419.               (emit-move.l (make-imm bits-FALSE) false-reg))))))))
  2420.  
  2421. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2422.  
  2423. ; FLONUM operation
  2424.  
  2425. (define (flo-oper oper1 oper2 opnds loc sn)
  2426.   (gen-guarantee-space 4) ; make sure there is enough space for flonum
  2427.   (move-opnd-to-loc68 (car opnds) atemp1 (sn-opnds (cdr opnds) (sn-opnd loc sn)))
  2428.   (oper1 (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  2429.   (let loop ((opnds (cdr opnds)))
  2430.     (if (not (null? opnds))
  2431.       (let* ((opnd (car opnds))
  2432.              (other-opnds (cdr opnds))
  2433.              (sn-other-opnds (sn-opnds other-opnds sn)))
  2434.         (move-opnd-to-loc68 opnd atemp1 sn-other-opnds)
  2435.         (oper2 (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  2436.         (loop (cdr opnds)))))
  2437.   (add-n-to-loc68 (* -4 pointer-size) heap-reg) ; allocate flonum
  2438.   (emit-move.l (make-imm (+ (* 2 1024) (* subtype-FLONUM 8)))
  2439.                (make-ind heap-reg))
  2440.   (let ((reg68 (if (reg? loc) (reg->reg68 loc) atemp1)))
  2441.     (emit-move.l heap-reg reg68)
  2442.     (emit-addq.l type-SUBTYPED reg68))
  2443.   (emit-fmov.d ftemp1 (make-disp* heap-reg pointer-size))
  2444.   (if (not (reg? loc))
  2445.     (move-opnd68-to-loc atemp1 loc sn)))
  2446.  
  2447. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2448.  
  2449. ; for checking for heap overflow after an allocation
  2450.  
  2451. (define (gen-guarantee-space n) ; n must be <= heap-allocation-fudge
  2452.   (set! pointers-allocated (+ pointers-allocated n))
  2453.   (if (> pointers-allocated heap-allocation-fudge)
  2454.     (begin
  2455.       (gen-guarantee-fudge)
  2456.       (set! pointers-allocated n))))
  2457.  
  2458. (define (gen-guarantee-fudge)
  2459.   (if (> pointers-allocated 0)
  2460.     (let ((lbl (new-lbl!)))
  2461.       (emit-cmp.l heap-lim-slot heap-reg)
  2462.       (emit-bcc   lbl)
  2463.       (gen-trap instr-source entry-frame #f #f heap-alloc1-trap lbl)
  2464.       (set! pointers-allocated 0))))
  2465.  
  2466. (define pointers-allocated '())
  2467.  
  2468. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2469.  
  2470. ; for type and subtype manipulation:
  2471.  
  2472. (define (gen-type opnds loc sn)
  2473.   (let* ((sn-loc (sn-opnd loc sn))
  2474.          (opnd (car opnds))
  2475.          (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2476.                   (reg->reg68 loc)
  2477.                   dtemp1)))
  2478.  
  2479.     (move-opnd-to-loc68 opnd reg68 sn-loc)
  2480.     (emit-and.l (make-imm 7) reg68)
  2481.     (emit-asl.l (make-imm 3) reg68)
  2482.     (move-opnd68-to-loc reg68 loc sn)))
  2483.  
  2484. (define (gen-type-cast opnds loc sn)
  2485.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2486.          (opnds (touch-operands opnds '(2) sn-loc)))
  2487.     (let ((first-opnd (car opnds))
  2488.           (second-opnd (cadr opnds)))
  2489.       (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) sn-loc sn))
  2490.              (o1 (opnd->opnd68 first-opnd #f (sn-opnd second-opnd sn-loc)))
  2491.              (o2 (opnd->opnd68 second-opnd (temp-in-opnd68 o1) sn-loc))
  2492.              (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2493.                       (reg->reg68 loc)
  2494.                       dtemp1)))
  2495.         (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2496.         (move-opnd68-to-loc68 (opnd68->true-opnd68 o1 (sn-opnd68 o2 sn-loc)) reg68)
  2497.         (emit-and.w (make-imm -8) reg68)
  2498.         (if (imm? o2)
  2499.           (let ((n (quotient (imm-val o2) 8)))
  2500.             (if (> n 0)
  2501.               (emit-addq.w n reg68)))
  2502.           (begin
  2503.             (move-opnd68-to-loc68 (opnd68->true-opnd68 o2 sn-loc) atemp1)
  2504.             (emit-exg atemp1 reg68)
  2505.             (emit-asr.l (make-imm 3) reg68)
  2506.             (emit-add.l atemp1 reg68)))
  2507.         (move-opnd68-to-loc reg68 loc sn)))))
  2508.  
  2509. (define (gen-subtype opnds loc sn)
  2510.   (let* ((sn-loc (sn-opnd loc sn))
  2511.          (opnd (touch-operand (car opnds) sn-loc))
  2512.          (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2513.                   (reg->reg68 loc)
  2514.                   dtemp1)))
  2515.  
  2516.     (move-opnd-to-loc68 opnd atemp1 sn-loc)
  2517.     (emit-moveq 0 reg68)
  2518.     (emit-move.b (make-ind atemp1) reg68)
  2519.     (move-opnd68-to-loc reg68 loc sn)))
  2520.  
  2521. (define (gen-subtype-set! opnds loc sn)
  2522.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2523.          (opnds (touch-operands opnds '0 sn-loc)))
  2524.     (let ((first-opnd (car opnds))
  2525.           (second-opnd (cadr opnds)))
  2526.       (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) sn-loc sn))
  2527.              (o1 (opnd->opnd68 first-opnd #f (sn-opnd second-opnd sn-loc)))
  2528.              (o2 (opnd->opnd68 second-opnd (temp-in-opnd68 o1) sn-loc)))
  2529.         (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2530.         (move-opnd68-to-loc68 (opnd68->true-opnd68 o1 (sn-opnd68 o2 sn-loc)) atemp1)
  2531.         (if (imm? o2)
  2532.           (emit-move.b (make-imm (imm-val o2)) (make-ind atemp1))
  2533.           (begin
  2534.             (move-opnd68-to-loc68 (opnd68->true-opnd68 o2 sn-loc) dtemp1)
  2535.             (emit-move.b dtemp1 (make-ind atemp1))))
  2536.         (if (and loc (not (eq? first-opnd loc)))
  2537.           (move-opnd68-to-loc atemp1 loc sn))))))
  2538.  
  2539. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2540.  
  2541. ; for vector manipulation:
  2542.  
  2543. (define (vector-select kind vector string vector8 vector16)
  2544.   (case kind
  2545.     ((STRING)   string)
  2546.     ((VECTOR8)  vector8)
  2547.     ((VECTOR16) vector16)
  2548.     (else       vector)))
  2549.  
  2550. (define (gen-vector kind)
  2551.   (lambda (opnds loc sn)
  2552.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2553.            (opnds (touch-operands opnds '0 sn-loc)))
  2554.       (let* ((n (length opnds))
  2555.              (bytes (+ pointer-size (* (vector-select kind 4 1 1 2) n)))
  2556.              (pointers (* (quotient (+ bytes (- pointer-size 1)) pointer-size)
  2557.                           pointer-size))
  2558.              (adjust (modulo (- bytes) 8)))
  2559.  
  2560.         (gen-guarantee-space pointers)
  2561.  
  2562.         (if (not (= adjust 0)) (emit-subq.l adjust heap-reg))
  2563.  
  2564.         (let loop ((opnds (reverse opnds)))
  2565.           (if (pair? opnds)
  2566.             (let* ((o (car opnds))
  2567.                    (sn-o (sn-opnds (cdr opnds) sn-loc)))
  2568.               (if (eq? kind 'VECTOR)
  2569.                 (move-opnd-to-loc68 o (make-pdec heap-reg) sn-o)
  2570.                 (begin
  2571.                   (move-opnd-to-loc68 o dtemp1 sn-o)
  2572.                   (emit-asr.l (make-imm 3) dtemp1)
  2573.                   (if (eq? kind 'VECTOR16)
  2574.                     (emit-move.w dtemp1 (make-pdec heap-reg))
  2575.                     (emit-move.b dtemp1 (make-pdec heap-reg)))))
  2576.               (loop (cdr opnds)))))
  2577.  
  2578.         (emit-move.l (make-imm (+ (* 256 (- bytes pointer-size))
  2579.                                   (* 8 (if (eq? kind 'VECTOR)
  2580.                                          subtype-VECTOR
  2581.                                              (if (imm? o2)
  2582.  
  2583.                     (begin
  2584.                       (move-opnd68-to-loc68
  2585.                         (opnd68->true-opnd68 o1 sn-third-opnd)
  2586.                         atemp1)
  2587.                       (make-disp* atemp1
  2588.                                   (+ (quotient (imm-val o2)
  2589.                                                (vector-select kind 2 8 8 4))
  2590.                                      offset)))
  2591.  
  2592.                       (begin
  2593.                         (move-opnd68-to-loc68
  2594.                           (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc))
  2595.                           dtemp1)
  2596.                         (emit-lsr.l (make-imm (vector-select kind 1 3 3 2))
  2597.                                     dtemp1)
  2598.                         (move-opnd68-to-loc68
  2599.                           (opnd68->true-opnd68 o1 sn-loc)
  2600.                           atemp1)
  2601.                         (if (not (memq kind '(VECTOR SLOT)))
  2602.                           (begin
  2603.                             (emit-move.l dtemp1 atemp2)
  2604.                             (make-inx atemp1 atemp2 offset))
  2605.                           (make-inx atemp1 dtemp1 offset))))))
  2606.  
  2607.             (if (memq kind '(VECTOR SLOT))
  2608.               (move-opnd-to-loc68 third-opnd loc68 sn-loc)
  2609.               (begin
  2610.                 (move-opnd-to-loc68 third-opnd dtemp1 sn-loc)
  2611.                 (emit-asr.l (make-imm 3) dtemp1)
  2612.                 (if (eq? kind 'VECTOR16)
  2613.                   (emit-move.w dtemp1 loc68)
  2614.                   (emit-move.b dtemp1 loc68))))
  2615.  
  2616.             (if (and loc (not (eq? first-opnd loc)))
  2617.               (copy-opnd-to-loc first-opnd loc sn))))))))
  2618.  
  2619. (define (gen-vector-shrink! kind)
  2620.   (lambda (opnds loc sn)
  2621.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2622.            (opnds (touch-operands opnds '0 sn-loc)))
  2623.       (let ((first-opnd (car opnds))
  2624.             (second-opnd (cadr opnds)))
  2625.         (let* ((sn-loc (if (and loc (not (eq? first-opnd loc)))
  2626.                          (sn-opnd first-opnd sn-loc)
  2627.                          sn))
  2628.                (o2 (opnd->opnd68 second-opnd #f (sn-opnd first-opnd sn-loc)))
  2629.                (o1 (opnd->opnd68 first-opnd (temp-in-opnd68 o2) sn-loc)))
  2630.           (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2631.           (move-opnd68-to-loc68
  2632.             (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc))
  2633.             dtemp1)
  2634.           (emit-asl.l (make-imm (vector-select kind 7 5 5 6)) dtemp1)
  2635.           (emit-move.l (opnd68->true-opnd68 o1 sn-loc) atemp1)
  2636.           (emit-move.b (make-ind atemp1) dtemp1)
  2637.           (emit-move.l dtemp1 (make-disp* atemp1 (- type-SUBTYPED)))
  2638.           (if (and loc (not (eq? first-opnd loc)))
  2639.             (move-opnd68-to-loc atemp1 loc sn)))))))
  2640.  
  2641. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2642.  
  2643. ; for CONDs that perform equality tests to constants
  2644.  
  2645. (define (gen-eq-test bits not? opnds lbl fs)
  2646.   (gen-compare* (opnd->opnd68 (touch-operand (car opnds) fs) #f fs)
  2647.                 (make-imm bits)
  2648.                 fs)
  2649.   (if not? (emit-bne lbl) (emit-beq lbl)))
  2650.  
  2651. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2652.  
  2653. ; for CONDs that perform comparisons
  2654.  
  2655. (define (gen-compare opnd1 opnd2 fs)
  2656.   (let* ((o1 (opnd->opnd68 opnd1 #f (sn-opnd opnd2 fs)))
  2657.          (o2 (opnd->opnd68 opnd2 (temp-in-opnd68 o1) fs)))
  2658.     (gen-compare* o1 o2 fs)))
  2659.  
  2660. (define (gen-compare* o1 o2 fs)
  2661.   (make-top-of-frame-if-stk-opnds68 o1 o2 fs)
  2662.   (let ((order-1-2
  2663.           (cond ((imm? o1)
  2664.                  (cmp-n-to-opnd68 (imm-val o1)
  2665.                                   (opnd68->true-opnd68 o2 fs)))
  2666.                 ((imm? o2)
  2667.                  (not (cmp-n-to-opnd68 (imm-val o2)
  2668.                                        (opnd68->true-opnd68 o1 fs))))
  2669.                 ((reg68? o1)
  2670.                  (emit-cmp.l (opnd68->true-opnd68 o2 fs) o1)
  2671.                  #f)
  2672.                 ((reg68? o2)
  2673.                  (emit-cmp.l (opnd68->true-opnd68 o1 fs) o2)
  2674.                  #t)
  2675.                 (else
  2676.                  (emit-move.l (opnd68->true-opnd68 o1 (sn-opnd68 o2 fs)) dtemp1)
  2677.                  (emit-cmp.l (opnd68->true-opnd68 o2 fs) dtemp1)
  2678.                  #f))))
  2679.     (shrink-frame fs)
  2680.     order-1-2))
  2681.  
  2682. (define (gen-compares branch< branch>= branch> branch<= not? opnds lbl fs)
  2683.   (gen-compares* gen-compare branch< branch>= branch> branch<= not? opnds lbl fs))
  2684.  
  2685. (define (gen-compares* gen-comp branch< branch>= branch> branch<= not? opnds lbl fs)
  2686.  
  2687.   (define (gen-compare-sequence opnd1 opnd2 rest)
  2688.     (if (null? rest)
  2689.  
  2690.       (if (gen-comp opnd1 opnd2 fs)
  2691.         (if not? (branch<= lbl) (branch> lbl))
  2692.         (if not? (branch>= lbl) (branch< lbl)))
  2693.                    
  2694.       (let ((order-1-2 (gen-comp opnd1 opnd2 (sn-opnd opnd2 (sn-opnds rest fs)))))
  2695.         (if (= current-fs fs) ; no need to adjust size of frame further...
  2696.  
  2697.           (if not?
  2698.             (begin
  2699.               (if order-1-2 (branch<= lbl) (branch>= lbl))
  2700.               (gen-compare-sequence opnd2 (car rest) (cdr rest)))
  2701.             (let ((exit-lbl (new-lbl!)))
  2702.               (if order-1-2 (branch<= exit-lbl) (branch>= exit-lbl))
  2703.               (gen-compare-sequence opnd2 (car rest) (cdr rest))
  2704.               (emit-label exit-lbl)))
  2705.  
  2706.           (if not?
  2707.             (let ((next-lbl (new-lbl!)))
  2708.               (if order-1-2 (branch> next-lbl) (branch< next-lbl))
  2709.               (shrink-frame fs)
  2710.               (emit-bra lbl)
  2711.               (emit-label next-lbl)
  2712.               (gen-compare-sequence opnd2 (car rest) (cdr rest)))
  2713.             (let* ((next-lbl (new-lbl!))
  2714.                    (exit-lbl (new-lbl!)))
  2715.               (if order-1-2 (branch> next-lbl) (branch< next-lbl))
  2716.               (shrink-frame fs)
  2717.               (emit-bra exit-lbl)
  2718.               (emit-label next-lbl)
  2719.               (gen-compare-sequence opnd2 (car rest) (cdr rest))
  2720.               (emit-label exit-lbl)))))))
  2721.  
  2722.   (if (or (null? opnds) (null? (cdr opnds)))
  2723.     (begin
  2724.       (shrink-frame fs)
  2725.       (if (not not?) (emit-bra lbl)))
  2726.     (gen-compare-sequence (car opnds) (cadr opnds) (cddr opnds))))
  2727.  
  2728. (define (gen-compare-flo opnd1 opnd2 fs)
  2729.   (let* ((o1 (opnd->opnd68 opnd1 #f (sn-opnd opnd2 fs)))
  2730.          (o2 (opnd->opnd68 opnd2 (temp-in-opnd68 o1) fs)))
  2731.     (make-top-of-frame-if-stk-opnds68 o1 o2 fs)
  2732.     (emit-move.l (opnd68->true-opnd68 o1 (sn-opnd68 o2 fs)) atemp1)
  2733.     (emit-move.l (opnd68->true-opnd68 o2 fs) atemp2)
  2734.     (emit-fmov.d (make-disp* atemp2 (- pointer-size type-SUBTYPED)) ftemp1)
  2735.     (emit-fcmp.d (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  2736.     #t))
  2737.  
  2738. (define (gen-compares-flo branch< branch>= branch> branch<= not? opnds lbl fs)
  2739.   (gen-compares* gen-compare-flo branch< branch>= branch> branch<= not? opnds lbl fs))
  2740.  
  2741. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2742.  
  2743. ; for CONDs that just have to test the value's type tag
  2744.  
  2745. (define (gen-type-test tag not? opnds lbl fs)
  2746.   (let ((opnd (touch-operand (car opnds) fs)))
  2747.     (let ((o (opnd->opnd68 opnd #f fs)))
  2748.  
  2749.       (define (mask-test set-reg correction)
  2750.         (emit-btst
  2751.           (if (= correction 0)
  2752.             (if (dreg? o)
  2753.               o
  2754.               (begin
  2755.                 (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)
  2756.                 dtemp1))
  2757.             (begin
  2758.               (if (not (eq? o dtemp1))
  2759.                 (emit-move.l (opnd68->true-opnd68 o fs) dtemp1))
  2760.               (emit-addq.w correction dtemp1)
  2761.               dtemp1))
  2762.           set-reg))
  2763.  
  2764.       (make-top-of-frame-if-stk-opnd68 o fs)
  2765.  
  2766.       (cond ((= tag 0)
  2767.              (if (eq? o dtemp1)
  2768.                (emit-and.w (make-imm 7) dtemp1)
  2769.                (begin
  2770.                  (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)
  2771.                  (emit-and.w (make-imm 7) dtemp1))))
  2772.             ((= tag type-PLACEHOLDER)
  2773.              (mask-test placeholder-reg 0))
  2774.             (else
  2775.              (mask-test pair-reg (modulo (- type-PAIR tag) 8))))
  2776.  
  2777.       (shrink-frame fs)
  2778.       (if not?
  2779.         (emit-bne lbl)
  2780.         (emit-beq lbl)))))
  2781.  
  2782. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2783.  
  2784. ; for CONDs that have to test the type tag of a hunk
  2785.  
  2786. (define (gen-subtype-test type not? opnds lbl fs)
  2787.   (let ((opnd (touch-operand (car opnds) fs)))
  2788.     (let ((o (opnd->opnd68 opnd #f fs))
  2789.           (cont-lbl (new-lbl!)))
  2790.       (make-top-of-frame-if-stk-opnd68 o fs)
  2791.       (if (not (eq? o dtemp1))
  2792.         (emit-move.l (opnd68->true-opnd68 o fs) dtemp1))
  2793.       (emit-move.l dtemp1 atemp1)
  2794.       (emit-addq.w (modulo (- type-PAIR type-SUBTYPED) 8) dtemp1)
  2795.       (emit-btst dtemp1 pair-reg)
  2796.       (shrink-frame fs)
  2797.       (if not?
  2798.         (emit-bne lbl)
  2799.         (emit-bne cont-lbl))
  2800.       (emit-cmp.b (make-imm (* type 8)) (make-ind atemp1))
  2801.       (if not?
  2802.         (emit-bne lbl)
  2803.         (emit-beq lbl))
  2804.       (emit-label cont-lbl))))
  2805.  
  2806. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2807.  
  2808. ; for CONDs that have to test for parity (even/odd)
  2809.  
  2810. (define (gen-even-test not? opnds lbl fs)
  2811.   (move-opnd-to-loc68 (touch-operand (car opnds) fs) dtemp1 fs)
  2812.   (emit-and.w (make-imm 8) dtemp1)
  2813.   (shrink-frame fs)
  2814.   (if not? (emit-bne lbl) (emit-beq lbl)))
  2815.  
  2816. ;------------------------------------------------------------------------------
  2817.  
  2818. ; Operation database:
  2819.  
  2820. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2821.  
  2822. ; some common specializations:
  2823.  
  2824. (define (def-spec name specializer-maker)
  2825.   (let ((proc-name (string->canonical-symbol name)))
  2826.     (let ((proc (prim-info proc-name)))
  2827.       (if proc
  2828.         (proc-obj-specialize-set! proc (specializer-maker proc proc-name))
  2829.         (compiler-internal-error
  2830.           "def-spec, unknown primitive:" name)))))
  2831.  
  2832. (define (safe name)
  2833.   (lambda (proc proc-name)
  2834.     (let ((spec (get-prim-info name)))
  2835.       (lambda (decls) spec))))
  2836.  
  2837. (define (unsafe name)
  2838.   (lambda (proc proc-name)
  2839.     (let ((spec (get-prim-info name)))
  2840.       (lambda (decls) (if (not (safe? decls)) spec proc)))))
  2841.  
  2842. (define (safe-arith fix-name flo-name)
  2843.   (arith #t fix-name flo-name))
  2844.  
  2845. (define (unsafe-arith fix-name flo-name)
  2846.   (arith #f fix-name flo-name))
  2847.  
  2848. (define (arith fix-safe? fix-name flo-name)
  2849.   (lambda (proc proc-name)
  2850.     (let ((fix-spec (if fix-name (get-prim-info fix-name) proc))
  2851.           (flo-spec (if flo-name (get-prim-info flo-name) proc)))
  2852.       (lambda (decls)
  2853.         (let ((arith (arith-implementation proc-name decls)))
  2854.           (cond ((eq? arith FIXNUM-sym)
  2855.                  (if (or fix-safe? (not (safe? decls))) fix-spec proc))
  2856.                 ((eq? arith FLONUM-sym)
  2857.                  (if (not (safe? decls)) flo-spec proc))
  2858.                 (else
  2859.                  proc)))))))
  2860.  
  2861. ;------------------------------------------------------------------------------
  2862.  
  2863. ; Operations:
  2864.  
  2865. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2866.  
  2867. (define-APPLY "##TYPE" #f (lambda (opnds loc sn)
  2868.   (gen-type opnds loc sn)))
  2869.  
  2870. (define-APPLY "##TYPE-CAST" #f (lambda (opnds loc sn)
  2871.   (gen-type-cast opnds loc sn)))
  2872.  
  2873. (define-APPLY "##SUBTYPE" #f (lambda (opnds loc sn)
  2874.   (gen-subtype opnds loc sn)))
  2875.  
  2876. (define-APPLY "##SUBTYPE-SET!" #t (lambda (opnds loc sn)
  2877.   (gen-subtype-set! opnds loc sn)))
  2878.  
  2879. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2880.  
  2881. (define-COND "##NOT" (lambda (not? opnds lbl fs)
  2882.   (gen-eq-test bits-FALSE not? opnds lbl fs)))
  2883.  
  2884. (define-COND "##NULL?" (lambda (not? opnds lbl fs)
  2885.   (gen-eq-test bits-NULL not? opnds lbl fs)))
  2886.  
  2887. (define-COND "##UNASSIGNED?" (lambda (not? opnds lbl fs)
  2888.   (gen-eq-test bits-UNASS not? opnds lbl fs)))
  2889.  
  2890. (define-COND "##UNBOUND?" (lambda (not? opnds lbl fs)
  2891.   (gen-eq-test bits-UNBOUND not? opnds lbl fs)))
  2892.  
  2893. (define-COND "##EQ?" (lambda (not? opnds lbl fs)
  2894.   (gen-compares emit-beq emit-bne emit-beq emit-bne
  2895.                 not?
  2896.                 (touch-operands opnds '0 fs)
  2897.                 lbl
  2898.                 fs)))
  2899.  
  2900. (define-COND "##FIXNUM?" (lambda (not? opnds lbl fs)
  2901.   (gen-type-test type-FIXNUM not? opnds lbl fs)))
  2902.  
  2903. (define-COND "##SPECIAL?" (lambda (not? opnds lbl fs)
  2904.   (gen-type-test type-SPECIAL not? opnds lbl fs)))
  2905.  
  2906. (define-COND "##PAIR?" (lambda (not? opnds lbl fs)
  2907.   (gen-type-test type-PAIR not? opnds lbl fs)))
  2908.  
  2909. (define-COND "##WEAK-PAIR?" (lambda (not? opnds lbl fs)
  2910.   (gen-type-test type-WEAK-PAIR not? opnds lbl fs)))
  2911.  
  2912. (define-COND "##SUBTYPED?" (lambda (not? opnds lbl fs)
  2913.   (gen-type-test type-SUBTYPED not? opnds lbl fs)))
  2914.  
  2915. (define-COND "##PROCEDURE?" (lambda (not? opnds lbl fs)
  2916.   (gen-type-test type-PROCEDURE not? opnds lbl fs)))
  2917.  
  2918. (define-COND "##PLACEHOLDER?" (lambda (not? opnds lbl fs)
  2919.   (gen-type-test type-PLACEHOLDER not? opnds lbl fs)))
  2920.  
  2921. (define-COND "##VECTOR?" (lambda (not? opnds lbl fs)
  2922.   (gen-subtype-test subtype-VECTOR not? opnds lbl fs)))
  2923.  
  2924. (define-COND "##SYMBOL?" (lambda (not? opnds lbl fs)
  2925.   (gen-subtype-test subtype-SYMBOL not? opnds lbl fs)))
  2926.  
  2927. (define-COND "##RATNUM?" (lambda (not? opnds lbl fs)
  2928.   (gen-subtype-test subtype-RATNUM not? opnds lbl fs)))
  2929.  
  2930. (define-COND "##CPXNUM?" (lambda (not? opnds lbl fs)
  2931.   (gen-subtype-test subtype-CPXNUM not? opnds lbl fs)))
  2932.  
  2933. (define-COND "##STRING?" (lambda (not? opnds lbl fs)
  2934.   (gen-subtype-test subtype-STRING not? opnds lbl fs)))
  2935.  
  2936. (define-COND "##BIGNUM?" (lambda (not? opnds lbl fs)
  2937.   (gen-subtype-test subtype-BIGNUM not? opnds lbl fs)))
  2938.  
  2939. (define-COND "##FLONUM?" (lambda (not? opnds lbl fs)
  2940.   (gen-subtype-test subtype-FLONUM not? opnds lbl fs)))
  2941.  
  2942. (define-COND "##CHAR?" (lambda (not? opnds lbl fs)
  2943.   (let ((opnd (touch-operand (car opnds) fs)))
  2944.     (let ((o (opnd->opnd68 opnd #f fs))
  2945.           (cont-lbl (new-lbl!)))
  2946.       (make-top-of-frame-if-stk-opnd68 o fs)
  2947.       (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)
  2948.       (if not?
  2949.         (emit-bmi lbl)
  2950.         (emit-bmi cont-lbl))
  2951.       (emit-addq.w (modulo (- type-PAIR type-SPECIAL) 8) dtemp1)
  2952.       (emit-btst dtemp1 pair-reg)
  2953.       (shrink-frame fs)
  2954.       (if not?
  2955.         (emit-bne lbl)
  2956.         (emit-beq lbl))
  2957.       (emit-label cont-lbl)))))
  2958.  
  2959. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2960.  
  2961. (define-APPLY "##FIXNUM.+" #f (lambda (opnds loc sn)
  2962.  
  2963.   (let* ((sn-loc (sn-opnd loc sn))
  2964.          (opnds (touch-operands opnds '0 sn-loc)))
  2965.     (cond ((null? opnds)
  2966.            (copy-opnd-to-loc (make-obj '0) loc sn))
  2967.           ((null? (cdr opnds))
  2968.            (copy-opnd-to-loc (car opnds) loc sn))
  2969.           ((or (reg? loc) (stk? loc))
  2970.            (commut-oper gen-add opnds loc sn #f '() '()))
  2971.           (else
  2972.            (gen-add opnds '() loc sn #f))))))
  2973.  
  2974. (define-APPLY "##FIXNUM.-" #f (lambda (opnds loc sn)
  2975.  
  2976.   (let* ((sn-loc (sn-opnd loc sn))
  2977.          (opnds (touch-operands opnds '0 sn-loc)))
  2978.     (gen-sub (car opnds) (cdr opnds) loc sn (any-contains-opnd? loc (cdr opnds))))))
  2979.  
  2980. (define-APPLY "##FIXNUM.*" #f (lambda (opnds loc sn)
  2981.  
  2982.   (let* ((sn-loc (sn-opnd loc sn))
  2983.          (opnds (touch-operands opnds '0 sn-loc)))
  2984.     (cond ((null? opnds)
  2985.            (copy-opnd-to-loc (make-obj '1) loc sn))
  2986.           ((null? (cdr opnds))
  2987.            (copy-opnd-to-loc (car opnds) loc sn))
  2988.           ((and (reg? loc) (not (eq? loc return-reg)))
  2989.            (commut-oper gen-mul opnds loc sn #f '() '()))
  2990.           (else
  2991.            (gen-mul opnds '() loc sn #f))))))
  2992.  
  2993. (define-APPLY "##FIXNUM.QUOTIENT" #f (lambda (opnds loc sn)
  2994.  
  2995.   (let* ((sn-loc (sn-opnd loc sn))
  2996.          (opnds (touch-operands opnds '0 sn-loc)))
  2997.     (gen-div (car opnds) (cdr opnds) loc sn (any-contains-opnd? loc (cdr opnds))))))
  2998.  
  2999. (define-APPLY "##FIXNUM.REMAINDER" #f (lambda (opnds loc sn)
  3000.  
  3001.   (let* ((sn-loc (sn-opnd loc sn))
  3002.          (opnds (touch-operands opnds '0 sn-loc)))
  3003.     (gen-rem (car opnds) (cadr opnds) loc sn))))
  3004.  
  3005. (define-APPLY "##FIXNUM.MODULO" #f (lambda (opnds loc sn)
  3006.  
  3007.   (let* ((sn-loc (sn-opnd loc sn))
  3008.          (opnds (touch-operands opnds '0 sn-loc)))
  3009.     (gen-mod (car opnds) (cadr opnds) loc sn))))
  3010.  
  3011. (define-APPLY "##FIXNUM.LOGIOR" #f (lambda (opnds loc sn)
  3012.  
  3013.   (let* ((sn-loc (sn-opnd loc sn))
  3014.          (opnds (touch-operands opnds '0 sn-loc)))
  3015.     (cond ((null? opnds)
  3016.            (copy-opnd-to-loc (make-obj '0) loc sn))
  3017.           ((null? (cdr opnds))
  3018.            (copy-opnd-to-loc (car opnds) loc sn))
  3019.           ((or (reg? loc) (stk? loc))
  3020.            (commut-oper gen-logior opnds loc sn #f '() '()))
  3021.           (else
  3022.            (gen-logior opnds '() loc sn #f))))))
  3023.  
  3024. (define-APPLY "##FIXNUM.LOGXOR" #f (lambda (opnds loc sn)
  3025.  
  3026.   (let* ((sn-loc (sn-opnd loc sn))
  3027.          (opnds (touch-operands opnds '0 sn-loc)))
  3028.     (cond ((null? opnds)
  3029.            (copy-opnd-to-loc (make-obj '0) loc sn))
  3030.           ((null? (cdr opnds))
  3031.            (copy-opnd-to-loc (car opnds) loc sn))
  3032.           ((or (reg? loc) (stk? loc))
  3033.            (commut-oper gen-logxor opnds loc sn #f '() '()))
  3034.           (else
  3035.            (gen-logxor opnds '() loc sn #f))))))
  3036.  
  3037. (define-APPLY "##FIXNUM.LOGAND" #f (lambda (opnds loc sn)
  3038.  
  3039.   (let* ((sn-loc (sn-opnd loc sn))
  3040.          (opnds (touch-operands opnds '0 sn-loc)))
  3041.     (cond ((null? opnds)
  3042.            (copy-opnd-to-loc (make-obj '-1) loc sn))
  3043.           ((null? (cdr opnds))
  3044.            (copy-opnd-to-loc (car opnds) loc sn))
  3045.           ((or (reg? loc) (stk? loc))
  3046.            (commut-oper gen-logand opnds loc sn #f '() '()))
  3047.           (else
  3048.            (gen-logand opnds '() loc sn #f))))))
  3049.  
  3050. (define-APPLY "##FIXNUM.LOGNOT" #f (lambda (opnds loc sn)
  3051.  
  3052.   (let* ((sn-loc (sn-opnd loc sn))
  3053.          (opnd (car (touch-operands opnds '0 sn-loc))))
  3054.  
  3055.     (if (and (or (reg? loc) (stk? loc))
  3056.              (not (eq? loc return-reg)))
  3057.  
  3058.       (begin
  3059.         (copy-opnd-to-loc opnd loc sn-loc)
  3060.         (let ((loc68 (loc->loc68 loc #f sn)))
  3061.           (make-top-of-frame-if-stk-opnd68 loc68 sn)
  3062.           (emit-not.l (opnd68->true-opnd68 loc68 sn))
  3063.           (emit-and.w (make-imm -8) (opnd68->true-opnd68 loc68 sn))))
  3064.  
  3065.       (begin
  3066.         (move-opnd-to-loc68 opnd dtemp1 (sn-opnd loc sn))
  3067.         (emit-not.l dtemp1)
  3068.         (emit-and.w (make-imm -8) dtemp1)
  3069.         (move-opnd68-to-loc dtemp1 loc sn))))))
  3070.  
  3071. (define-APPLY "##FIXNUM.ASH" #f (gen-shift emit-asr.l))
  3072.  
  3073. (define-APPLY "##FIXNUM.LSH" #f (gen-shift emit-lsr.l))
  3074.  
  3075. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3076.  
  3077. (define-COND "##FIXNUM.ZERO?" (lambda (not? opnds lbl fs)
  3078.   (gen-eq-test 0 not? opnds lbl fs)))
  3079.  
  3080. (define-COND "##FIXNUM.POSITIVE?" (lambda (not? opnds lbl fs)
  3081.   (gen-compares emit-bgt emit-ble emit-blt emit-bge
  3082.                 not?
  3083.                 (list (touch-operand (car opnds) fs) (make-obj '0))
  3084.                 lbl
  3085.                 fs)))
  3086.  
  3087. (define-COND "##FIXNUM.NEGATIVE?" (lambda (not? opnds lbl fs)
  3088.   (gen-compares emit-blt emit-bge emit-bgt emit-ble
  3089.                 not?
  3090.                 (list (touch-operand (car opnds) fs) (make-obj '0))
  3091.                 lbl
  3092.                 fs)))
  3093.  
  3094. (define-COND "##FIXNUM.ODD?" (lambda (not? opnds lbl fs)
  3095.   (gen-even-test (not not?) opnds lbl fs)))
  3096.  
  3097. (define-COND "##FIXNUM.EVEN?" (lambda (not? opnds lbl fs)
  3098.   (gen-even-test not? opnds lbl fs)))
  3099.  
  3100. (define-COND "##FIXNUM.=" (lambda (not? opnds lbl fs)
  3101.   (gen-compares emit-beq emit-bne emit-beq emit-bne
  3102.                 not?
  3103.                 (touch-operands opnds '0 fs)
  3104.                 lbl
  3105.                 fs)))
  3106.  
  3107. (define-COND "##FIXNUM.<" (lambda (not? opnds lbl fs)
  3108.   (gen-compares emit-blt emit-bge emit-bgt emit-ble
  3109.                 not?
  3110.                 (touch-operands opnds '0 fs)
  3111.                 lbl
  3112.                 fs)))
  3113.  
  3114. (define-COND "##FIXNUM.>" (lambda (not? opnds lbl fs)
  3115.   (gen-compares emit-bgt emit-ble emit-blt emit-bge
  3116.                 not?
  3117.                 (touch-operands opnds '0 fs)
  3118.                 lbl
  3119.                 fs)))
  3120.  
  3121. (define-COND "##FIXNUM.<=" (lambda (not? opnds lbl fs)
  3122.   (gen-compares emit-ble emit-bgt emit-bge emit-blt
  3123.                 not?
  3124.                 (touch-operands opnds '0 fs)
  3125.                 lbl
  3126.                 fs)))
  3127.  
  3128. (define-COND "##FIXNUM.>=" (lambda (not? opnds lbl fs)
  3129.   (gen-compares emit-bge emit-blt emit-ble emit-bgt
  3130.                 not?
  3131.                 (touch-operands opnds '0 fs)
  3132.                 lbl
  3133.                 fs)))
  3134.  
  3135. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3136.  
  3137. (define-APPLY "##FLONUM.->FIXNUM" #f (lambda (opnds loc sn)
  3138.   (let* ((sn-loc (sn-opnd loc sn))
  3139.          (opnds (touch-operands opnds '0 sn-loc)))
  3140.     (move-opnd-to-loc68 (car opnds) atemp1 sn-loc)
  3141.     (let ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  3142.                    (reg->reg68 loc)
  3143.                    dtemp1)))
  3144.       (emit-fmov.d (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  3145.       (emit-fmov.l ftemp1 reg68)
  3146.       (emit-asl.l (make-imm 3) reg68)
  3147.       (if (not (and (reg? loc) (not (eq? loc return-reg))))
  3148.         (move-opnd68-to-loc reg68 loc sn))))))
  3149.  
  3150. (define-APPLY "##FLONUM.<-FIXNUM" #f (lambda (opnds loc sn)
  3151.   (gen-guarantee-space 4) ; make sure there is enough space for flonum
  3152.   (move-opnd-to-loc68 (car opnds) dtemp1 (sn-opnds (cdr opnds) (sn-opnd loc sn)))
  3153.   (emit-asr.l (make-imm 3) dtemp1)
  3154.   (emit-fmov.l dtemp1 ftemp1)
  3155.   (add-n-to-loc68 (* -4 pointer-size) heap-reg) ; allocate flonum
  3156.   (emit-move.l (make-imm (+ (* 2 1024) (* subtype-FLONUM 8)))
  3157.                (make-ind heap-reg))
  3158.   (let ((reg68 (if (reg? loc) (reg->reg68 loc) atemp1)))
  3159.     (emit-move.l heap-reg reg68)
  3160.     (emit-addq.l type-SUBTYPED reg68))
  3161.   (emit-fmov.d ftemp1 (make-disp* heap-reg pointer-size))
  3162.   (if (not (reg? loc))
  3163.     (move-opnd68-to-loc atemp1 loc sn))))
  3164.  
  3165. (define-APPLY "##FLONUM.+" #f (lambda (opnds loc sn)
  3166.  
  3167.   (let* ((sn-loc (sn-opnd loc sn))
  3168.          (opnds (touch-operands opnds '0 sn-loc)))
  3169.     (cond ((null? opnds)
  3170.            (copy-opnd-to-loc (make-obj inexact-0) loc sn))
  3171.           ((null? (cdr opnds))
  3172.            (copy-opnd-to-loc (car opnds) loc sn))
  3173.           (else
  3174.            (flo-oper emit-fmov.d emit-fadd.d opnds loc sn))))))
  3175.  
  3176. (define-APPLY "##FLONUM.-" #f (lambda (opnds loc sn)
  3177.  
  3178.   (let* ((sn-loc (sn-opnd loc sn))
  3179.          (opnds (touch-operands opnds '0 sn-loc)))
  3180.     (if (null? (cdr opnds))
  3181.       (flo-oper emit-fneg.d #f opnds loc sn)
  3182.       (flo-oper emit-fmov.d emit-fsub.d opnds loc sn)))))
  3183.  
  3184. (define-APPLY "##FLONUM.*" #f (lambda (opnds loc sn)
  3185.  
  3186.   (let* ((sn-loc (sn-opnd loc sn))
  3187.          (opnds (touch-operands opnds '0 sn-loc)))
  3188.     (cond ((null? opnds)
  3189.            (copy-opnd-to-loc (make-obj inexact-+1) loc sn))
  3190.           ((null? (cdr opnds))
  3191.            (copy-opnd-to-loc (car opnds) loc sn))
  3192.           (else
  3193.            (flo-oper emit-fmov.d emit-fmul.d opnds loc sn))))))
  3194.  
  3195. (define-APPLY "##FLONUM./" #f (lambda (opnds loc sn)
  3196.  
  3197.   (let* ((sn-loc (sn-opnd loc sn))
  3198.          (opnds (touch-operands opnds '0 sn-loc)))
  3199.     (if (null? (cdr opnds))
  3200.       (flo-oper emit-fmov.d emit-fdiv.d (cons (make-obj inexact-+1) opnds) loc sn)
  3201.       (flo-oper emit-fmov.d emit-fdiv.d opnds loc sn)))))
  3202.  
  3203. (define-APPLY "##FLONUM.ABS" #f (lambda (opnds loc sn)
  3204.   (let* ((sn-loc (sn-opnd loc sn))
  3205.          (opnds (touch-operands opnds '0 sn-loc)))
  3206.     (flo-oper emit-fabs.d #f opnds loc sn))))
  3207.  
  3208. (define-APPLY "##FLONUM.TRUNCATE" #f (lambda (opnds loc sn)
  3209.   (let* ((sn-loc (sn-opnd loc sn))
  3210.          (opnds (touch-operands opnds '0 sn-loc)))
  3211.     (flo-oper emit-fintrz.d #f opnds loc sn))))
  3212.  
  3213. (define-APPLY "##FLONUM.ROUND" #f (lambda (opnds loc sn)
  3214.   (let* ((sn-loc (sn-opnd loc sn))
  3215.          (opnds (touch-operands opnds '0 sn-loc)))
  3216.     (flo-oper emit-fint.d #f opnds loc sn))))
  3217.  
  3218. (define-APPLY "##FLONUM.EXP" #f (lambda (opnds loc sn)
  3219.   (let* ((sn-loc (sn-opnd loc sn))
  3220.          (opnds (touch-operands opnds '0 sn-loc)))
  3221.     (flo-oper emit-fetox.d #f opnds loc sn))))
  3222.  
  3223. (define-APPLY "##FLONUM.LOG" #f (lambda (opnds loc sn)
  3224.   (let* ((sn-loc (sn-opnd loc sn))
  3225.          (opnds (touch-operands opnds '0 sn-loc)))
  3226.     (flo-oper emit-flogn.d #f opnds loc sn))))
  3227.  
  3228. (define-APPLY "##FLONUM.SIN" #f (lambda (opnds loc sn)
  3229.   (let* ((sn-loc (sn-opnd loc sn))
  3230.          (opnds (touch-operands opnds '0 sn-loc)))
  3231.     (flo-oper emit-fsin.d #f opnds loc sn))))
  3232.  
  3233. (define-APPLY "##FLONUM.COS" #f (lambda (opnds loc sn)
  3234.   (let* ((sn-loc (sn-opnd loc sn))
  3235.          (opnds (touch-operands opnds '0 sn-loc)))
  3236.     (flo-oper emit-fcos.d #f opnds loc sn))))
  3237.  
  3238. (define-APPLY "##FLONUM.TAN" #f (lambda (opnds loc sn)
  3239.   (let* ((sn-loc (sn-opnd loc sn))
  3240.          (opnds (touch-operands opnds '0 sn-loc)))
  3241.     (flo-oper emit-ftan.d #f opnds loc sn))))
  3242.  
  3243. (define-APPLY "##FLONUM.ASIN" #f (lambda (opnds loc sn)
  3244.   (let* ((sn-loc (sn-opnd loc sn))
  3245.          (opnds (touch-operands opnds '0 sn-loc)))
  3246.     (flo-oper emit-fasin.d #f opnds loc sn))))
  3247.  
  3248. (define-APPLY "##FLONUM.ACOS" #f (lambda (opnds loc sn)
  3249.   (let* ((sn-loc (sn-opnd loc sn))
  3250.          (opnds (touch-operands opnds '0 sn-loc)))
  3251.     (flo-oper emit-facos.d #f opnds loc sn))))
  3252.  
  3253. (define-APPLY "##FLONUM.ATAN" #f (lambda (opnds loc sn)
  3254.   (let*R"))
  3255. (def-spec "CADDR"            (unsafe "##CADDR"))
  3256. (def-spec "CDAAR"            (unsafe "##CDAAR"))
  3257. (def-spec "CDADR"            (unsafe "##CDADR"))
  3258. (def-spec "CDDAR"            (unsafe "##CDDAR"))
  3259. (def-spec "CDDDR"            (unsafe "##CDDDR"))
  3260. (def-spec "CAAAAR"           (unsafe "##CAAAAR"))
  3261. (def-spec "CAAADR"           (unsafe "##CAAADR"))
  3262. (def-spec "CAADAR"           (unsafe "##CAADAR"))
  3263. (def-spec "CAADDR"           (unsafe "##CAADDR"))
  3264. (def-spec "CADAAR"           (unsafe "##CADAAR"))
  3265. (def-spec "CADADR"           (unsafe "##CADADR"))
  3266. (def-spec "CADDAR"           (unsafe "##CADDAR"))
  3267. (def-spec "CADDDR"           (unsafe "##CADDDR"))
  3268. (def-spec "CDAAAR"           (unsafe "##CDAAAR"))
  3269. (def-spec "CDAADR"           (unsafe "##CDAADR"))
  3270. (def-spec "CDADAR"           (unsafe "##CDADAR"))
  3271. (def-spec "CDADDR"           (unsafe "##CDADDR"))
  3272. (def-spec "CDDAAR"           (unsafe "##CDDAAR"))
  3273. (def-spec "CDDADR"           (unsafe "##CDDADR"))
  3274. (def-spec "CDDDAR"           (unsafe "##CDDDAR"))
  3275. (def-spec "CDDDDR"           (unsafe "##CDDDDR"))
  3276.  
  3277. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3278.  
  3279. (def-spec "VECTOR"           (safe "##VECTOR"))
  3280. (def-spec "VECTOR-LENGTH"    (unsafe "##VECTOR-LENGTH"))
  3281. (def-spec "VECTOR-REF"       (unsafe "##VECTOR-REF"))
  3282. (def-spec "VECTOR-SET!"      (unsafe "##VECTOR-SET!"))
  3283.  
  3284. (def-spec "STRING"           (safe "##STRING"))
  3285. (def-spec "STRING-LENGTH"    (unsafe "##STRING-LENGTH"))
  3286. (def-spec "STRING-REF"       (unsafe "##STRING-REF"))
  3287. (def-spec "STRING-SET!"      (unsafe "##STRING-SET!"))
  3288.  
  3289. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3290.  
  3291. (def-spec "TOUCH"            (safe "##TOUCH"))
  3292.  
  3293. ;------------------------------------------------------------------------------
  3294.  
  3295. (let ((targ (make-target 3 'M68000)))
  3296.  
  3297.   (target-begin!-set! targ (lambda (info-port) (begin! info-port targ)))
  3298.  
  3299.   (put-target targ))
  3300.  
  3301. ;==============================================================================
  3302.